Annotation of qemu/roms/ipxe/src/interface/efi/efi_console.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (C) 2008 Michael Brown <[email protected]>.
        !             3:  *
        !             4:  * This program is free software; you can redistribute it and/or
        !             5:  * modify it under the terms of the GNU General Public License as
        !             6:  * published by the Free Software Foundation; either version 2 of the
        !             7:  * License, or any later version.
        !             8:  *
        !             9:  * This program is distributed in the hope that it will be useful, but
        !            10:  * WITHOUT ANY WARRANTY; without even the implied warranty of
        !            11:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
        !            12:  * General Public License for more details.
        !            13:  *
        !            14:  * You should have received a copy of the GNU General Public License
        !            15:  * along with this program; if not, write to the Free Software
        !            16:  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
        !            17:  */
        !            18: 
        !            19: FILE_LICENCE ( GPL2_OR_LATER );
        !            20: 
        !            21: #include <stddef.h>
        !            22: #include <assert.h>
        !            23: #include <ipxe/efi/efi.h>
        !            24: #include <ipxe/ansiesc.h>
        !            25: #include <ipxe/console.h>
        !            26: 
        !            27: #define ATTR_BOLD              0x08
        !            28: 
        !            29: #define ATTR_FCOL_MASK         0x07
        !            30: #define ATTR_FCOL_BLACK                0x00
        !            31: #define ATTR_FCOL_BLUE         0x01
        !            32: #define ATTR_FCOL_GREEN                0x02
        !            33: #define ATTR_FCOL_CYAN         0x03
        !            34: #define ATTR_FCOL_RED          0x04
        !            35: #define ATTR_FCOL_MAGENTA      0x05
        !            36: #define ATTR_FCOL_YELLOW       0x06
        !            37: #define ATTR_FCOL_WHITE                0x07
        !            38: 
        !            39: #define ATTR_BCOL_MASK         0x70
        !            40: #define ATTR_BCOL_BLACK                0x00
        !            41: #define ATTR_BCOL_BLUE         0x10
        !            42: #define ATTR_BCOL_GREEN                0x20
        !            43: #define ATTR_BCOL_CYAN         0x30
        !            44: #define ATTR_BCOL_RED          0x40
        !            45: #define ATTR_BCOL_MAGENTA      0x50
        !            46: #define ATTR_BCOL_YELLOW       0x60
        !            47: #define ATTR_BCOL_WHITE                0x70
        !            48: 
        !            49: #define ATTR_DEFAULT           ATTR_FCOL_WHITE
        !            50: 
        !            51: /** Current character attribute */
        !            52: static unsigned int efi_attr = ATTR_DEFAULT;
        !            53: 
        !            54: /**
        !            55:  * Handle ANSI CUP (cursor position)
        !            56:  *
        !            57:  * @v count            Parameter count
        !            58:  * @v params[0]                Row (1 is top)
        !            59:  * @v params[1]                Column (1 is left)
        !            60:  */
        !            61: static void efi_handle_cup ( unsigned int count __unused, int params[] ) {
        !            62:        EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *conout = efi_systab->ConOut;
        !            63:        int cx = ( params[1] - 1 );
        !            64:        int cy = ( params[0] - 1 );
        !            65: 
        !            66:        if ( cx < 0 )
        !            67:                cx = 0;
        !            68:        if ( cy < 0 )
        !            69:                cy = 0;
        !            70: 
        !            71:        conout->SetCursorPosition ( conout, cx, cy );
        !            72: }
        !            73: 
        !            74: /**
        !            75:  * Handle ANSI ED (erase in page)
        !            76:  *
        !            77:  * @v count            Parameter count
        !            78:  * @v params[0]                Region to erase
        !            79:  */
        !            80: static void efi_handle_ed ( unsigned int count __unused,
        !            81:                             int params[] __unused ) {
        !            82:        EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *conout = efi_systab->ConOut;
        !            83: 
        !            84:        /* We assume that we always clear the whole screen */
        !            85:        assert ( params[0] == ANSIESC_ED_ALL );
        !            86: 
        !            87:        conout->ClearScreen ( conout );
        !            88: }
        !            89: 
        !            90: /**
        !            91:  * Handle ANSI SGR (set graphics rendition)
        !            92:  *
        !            93:  * @v count            Parameter count
        !            94:  * @v params           List of graphic rendition aspects
        !            95:  */
        !            96: static void efi_handle_sgr ( unsigned int count, int params[] ) {
        !            97:        EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *conout = efi_systab->ConOut;
        !            98:        static const uint8_t efi_attr_fcols[10] = {
        !            99:                ATTR_FCOL_BLACK, ATTR_FCOL_RED, ATTR_FCOL_GREEN,
        !           100:                ATTR_FCOL_YELLOW, ATTR_FCOL_BLUE, ATTR_FCOL_MAGENTA,
        !           101:                ATTR_FCOL_CYAN, ATTR_FCOL_WHITE,
        !           102:                ATTR_FCOL_WHITE, ATTR_FCOL_WHITE /* defaults */
        !           103:        };
        !           104:        static const uint8_t efi_attr_bcols[10] = {
        !           105:                ATTR_BCOL_BLACK, ATTR_BCOL_RED, ATTR_BCOL_GREEN,
        !           106:                ATTR_BCOL_YELLOW, ATTR_BCOL_BLUE, ATTR_BCOL_MAGENTA,
        !           107:                ATTR_BCOL_CYAN, ATTR_BCOL_WHITE,
        !           108:                ATTR_BCOL_BLACK, ATTR_BCOL_BLACK /* defaults */
        !           109:        };
        !           110:        unsigned int i;
        !           111:        int aspect;
        !           112: 
        !           113:        for ( i = 0 ; i < count ; i++ ) {
        !           114:                aspect = params[i];
        !           115:                if ( aspect == 0 ) {
        !           116:                        efi_attr = ATTR_DEFAULT;
        !           117:                } else if ( aspect == 1 ) {
        !           118:                        efi_attr |= ATTR_BOLD;
        !           119:                } else if ( aspect == 22 ) {
        !           120:                        efi_attr &= ~ATTR_BOLD;
        !           121:                } else if ( ( aspect >= 30 ) && ( aspect <= 39 ) ) {
        !           122:                        efi_attr &= ~ATTR_FCOL_MASK;
        !           123:                        efi_attr |= efi_attr_fcols[ aspect - 30 ];
        !           124:                } else if ( ( aspect >= 40 ) && ( aspect <= 49 ) ) {
        !           125:                        efi_attr &= ~ATTR_BCOL_MASK;
        !           126:                        efi_attr |= efi_attr_bcols[ aspect - 40 ];
        !           127:                }
        !           128:        }
        !           129: 
        !           130:        conout->SetAttribute ( conout, efi_attr );
        !           131: }
        !           132: 
        !           133: /** EFI console ANSI escape sequence handlers */
        !           134: static struct ansiesc_handler efi_ansiesc_handlers[] = {
        !           135:        { ANSIESC_CUP, efi_handle_cup },
        !           136:        { ANSIESC_ED, efi_handle_ed },
        !           137:        { ANSIESC_SGR, efi_handle_sgr },
        !           138:        { 0, NULL }
        !           139: };
        !           140: 
        !           141: /** EFI console ANSI escape sequence context */
        !           142: static struct ansiesc_context efi_ansiesc_ctx = {
        !           143:        .handlers = efi_ansiesc_handlers,
        !           144: };
        !           145: 
        !           146: /**
        !           147:  * Print a character to EFI console
        !           148:  *
        !           149:  * @v character                Character to be printed
        !           150:  */
        !           151: static void efi_putchar ( int character ) {
        !           152:        EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *conout = efi_systab->ConOut;
        !           153:        wchar_t wstr[] = { character, 0 };
        !           154: 
        !           155:        /* Intercept ANSI escape sequences */
        !           156:        character = ansiesc_process ( &efi_ansiesc_ctx, character );
        !           157:        if ( character < 0 )
        !           158:                return;
        !           159: 
        !           160:        conout->OutputString ( conout, wstr );
        !           161: }
        !           162: 
        !           163: /**
        !           164:  * Pointer to current ANSI output sequence
        !           165:  *
        !           166:  * While we are in the middle of returning an ANSI sequence for a
        !           167:  * special key, this will point to the next character to return.  When
        !           168:  * not in the middle of such a sequence, this will point to a NUL
        !           169:  * (note: not "will be NULL").
        !           170:  */
        !           171: static const char *ansi_input = "";
        !           172: 
        !           173: /** Mapping from EFI scan codes to ANSI escape sequences */
        !           174: static const char *ansi_sequences[] = {
        !           175:        [SCAN_UP] = "[A",
        !           176:        [SCAN_DOWN] = "[B",
        !           177:        [SCAN_RIGHT] = "[C",
        !           178:        [SCAN_LEFT] = "[D",
        !           179:        [SCAN_HOME] = "[H",
        !           180:        [SCAN_END] = "[F",
        !           181:        [SCAN_INSERT] = "[2~",
        !           182:        /* EFI translates an incoming backspace via the serial console
        !           183:         * into a SCAN_DELETE.  There's not much we can do about this.
        !           184:         */
        !           185:        [SCAN_DELETE] = "[3~",
        !           186:        [SCAN_PAGE_UP] = "[5~",
        !           187:        [SCAN_PAGE_DOWN] = "[6~",
        !           188:        /* EFI translates some (but not all) incoming escape sequences
        !           189:         * via the serial console into equivalent scancodes.  When it
        !           190:         * doesn't recognise a sequence, it helpfully(!) translates
        !           191:         * the initial ESC and passes the remainder through verbatim.
        !           192:         * Treating SCAN_ESC as equivalent to an empty escape sequence
        !           193:         * works around this bug.
        !           194:         */
        !           195:        [SCAN_ESC] = "",
        !           196: };
        !           197: 
        !           198: /**
        !           199:  * Get ANSI escape sequence corresponding to EFI scancode
        !           200:  *
        !           201:  * @v scancode         EFI scancode
        !           202:  * @ret ansi_seq       ANSI escape sequence, if any, otherwise NULL
        !           203:  */
        !           204: static const char * scancode_to_ansi_seq ( unsigned int scancode ) {
        !           205:        if ( scancode < ( sizeof ( ansi_sequences ) /
        !           206:                          sizeof ( ansi_sequences[0] ) ) ) {
        !           207:                return ansi_sequences[scancode];
        !           208:        }
        !           209:        return NULL;
        !           210: }
        !           211: 
        !           212: /**
        !           213:  * Get character from EFI console
        !           214:  *
        !           215:  * @ret character      Character read from console
        !           216:  */
        !           217: static int efi_getchar ( void ) {
        !           218:        EFI_SIMPLE_TEXT_INPUT_PROTOCOL *conin = efi_systab->ConIn;
        !           219:        const char *ansi_seq;
        !           220:        EFI_INPUT_KEY key;
        !           221:        EFI_STATUS efirc;
        !           222: 
        !           223:        /* If we are mid-sequence, pass out the next byte */
        !           224:        if ( *ansi_input )
        !           225:                return *(ansi_input++);
        !           226: 
        !           227:        /* Read key from real EFI console */
        !           228:        if ( ( efirc = conin->ReadKeyStroke ( conin, &key ) ) != 0 ) {
        !           229:                DBG ( "EFI could not read keystroke: %s\n",
        !           230:                      efi_strerror ( efirc ) );
        !           231:                return 0;
        !           232:        }
        !           233:        DBG2 ( "EFI read key stroke with unicode %04x scancode %04x\n",
        !           234:               key.UnicodeChar, key.ScanCode );
        !           235: 
        !           236:        /* If key has a Unicode representation, return it */
        !           237:        if ( key.UnicodeChar )
        !           238:                return key.UnicodeChar;
        !           239: 
        !           240:        /* Otherwise, check for a special key that we know about */
        !           241:        if ( ( ansi_seq = scancode_to_ansi_seq ( key.ScanCode ) ) ) {
        !           242:                /* Start of escape sequence: return ESC (0x1b) */
        !           243:                ansi_input = ansi_seq;
        !           244:                return 0x1b;
        !           245:        }
        !           246: 
        !           247:        return 0;
        !           248: }
        !           249: 
        !           250: /**
        !           251:  * Check for character ready to read from EFI console
        !           252:  *
        !           253:  * @ret True           Character available to read
        !           254:  * @ret False          No character available to read
        !           255:  */
        !           256: static int efi_iskey ( void ) {
        !           257:        EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
        !           258:        EFI_SIMPLE_TEXT_INPUT_PROTOCOL *conin = efi_systab->ConIn;
        !           259:        EFI_STATUS efirc;
        !           260: 
        !           261:        /* If we are mid-sequence, we are always ready */
        !           262:        if ( *ansi_input )
        !           263:                return 1;
        !           264: 
        !           265:        /* Check to see if the WaitForKey event has fired */
        !           266:        if ( ( efirc = bs->CheckEvent ( conin->WaitForKey ) ) == 0 )
        !           267:                return 1;
        !           268: 
        !           269:        return 0;
        !           270: }
        !           271: 
        !           272: struct console_driver efi_console __console_driver = {
        !           273:        .putchar = efi_putchar,
        !           274:        .getchar = efi_getchar,
        !           275:        .iskey = efi_iskey,
        !           276: };

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.