00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 FILE_LICENCE ( GPL2_OR_LATER );
00020
00021 #include <assert.h>
00022 #include <realmode.h>
00023 #include <console.h>
00024 #include <gpxe/ansiesc.h>
00025
00026 #define ATTR_BOLD 0x08
00027
00028 #define ATTR_FCOL_MASK 0x07
00029 #define ATTR_FCOL_BLACK 0x00
00030 #define ATTR_FCOL_BLUE 0x01
00031 #define ATTR_FCOL_GREEN 0x02
00032 #define ATTR_FCOL_CYAN 0x03
00033 #define ATTR_FCOL_RED 0x04
00034 #define ATTR_FCOL_MAGENTA 0x05
00035 #define ATTR_FCOL_YELLOW 0x06
00036 #define ATTR_FCOL_WHITE 0x07
00037
00038 #define ATTR_BCOL_MASK 0x70
00039 #define ATTR_BCOL_BLACK 0x00
00040 #define ATTR_BCOL_BLUE 0x10
00041 #define ATTR_BCOL_GREEN 0x20
00042 #define ATTR_BCOL_CYAN 0x30
00043 #define ATTR_BCOL_RED 0x40
00044 #define ATTR_BCOL_MAGENTA 0x50
00045 #define ATTR_BCOL_YELLOW 0x60
00046 #define ATTR_BCOL_WHITE 0x70
00047
00048 #define ATTR_DEFAULT ATTR_FCOL_WHITE
00049
00050
00051 static unsigned int bios_attr = ATTR_DEFAULT;
00052
00053
00054
00055
00056
00057
00058
00059
00060 static void bios_handle_cup ( unsigned int count __unused, int params[] ) {
00061 int cx = ( params[1] - 1 );
00062 int cy = ( params[0] - 1 );
00063
00064 if ( cx < 0 )
00065 cx = 0;
00066 if ( cy < 0 )
00067 cy = 0;
00068
00069 __asm__ __volatile__ ( REAL_CODE ( "sti\n\t"
00070 "int $0x10\n\t"
00071 "cli\n\t" )
00072 : : "a" ( 0x0200 ), "b" ( 1 ),
00073 "d" ( ( cy << 8 ) | cx ) );
00074 }
00075
00076
00077
00078
00079
00080
00081
00082 static void bios_handle_ed ( unsigned int count __unused,
00083 int params[] __unused ) {
00084
00085 assert ( params[0] == ANSIESC_ED_ALL );
00086
00087 __asm__ __volatile__ ( REAL_CODE ( "sti\n\t"
00088 "int $0x10\n\t"
00089 "cli\n\t" )
00090 : : "a" ( 0x0600 ), "b" ( bios_attr << 8 ),
00091 "c" ( 0 ), "d" ( 0xffff ) );
00092 }
00093
00094
00095
00096
00097
00098
00099
00100 static void bios_handle_sgr ( unsigned int count, int params[] ) {
00101 static const uint8_t bios_attr_fcols[10] = {
00102 ATTR_FCOL_BLACK, ATTR_FCOL_RED, ATTR_FCOL_GREEN,
00103 ATTR_FCOL_YELLOW, ATTR_FCOL_BLUE, ATTR_FCOL_MAGENTA,
00104 ATTR_FCOL_CYAN, ATTR_FCOL_WHITE,
00105 ATTR_FCOL_WHITE, ATTR_FCOL_WHITE
00106 };
00107 static const uint8_t bios_attr_bcols[10] = {
00108 ATTR_BCOL_BLACK, ATTR_BCOL_RED, ATTR_BCOL_GREEN,
00109 ATTR_BCOL_YELLOW, ATTR_BCOL_BLUE, ATTR_BCOL_MAGENTA,
00110 ATTR_BCOL_CYAN, ATTR_BCOL_WHITE,
00111 ATTR_BCOL_BLACK, ATTR_BCOL_BLACK
00112 };
00113 unsigned int i;
00114 int aspect;
00115
00116 for ( i = 0 ; i < count ; i++ ) {
00117 aspect = params[i];
00118 if ( aspect == 0 ) {
00119 bios_attr = ATTR_DEFAULT;
00120 } else if ( aspect == 1 ) {
00121 bios_attr |= ATTR_BOLD;
00122 } else if ( aspect == 22 ) {
00123 bios_attr &= ~ATTR_BOLD;
00124 } else if ( ( aspect >= 30 ) && ( aspect <= 39 ) ) {
00125 bios_attr &= ~ATTR_FCOL_MASK;
00126 bios_attr |= bios_attr_fcols[ aspect - 30 ];
00127 } else if ( ( aspect >= 40 ) && ( aspect <= 49 ) ) {
00128 bios_attr &= ~ATTR_BCOL_MASK;
00129 bios_attr |= bios_attr_bcols[ aspect - 40 ];
00130 }
00131 }
00132 }
00133
00134
00135 static struct ansiesc_handler bios_ansiesc_handlers[] = {
00136 { ANSIESC_CUP, bios_handle_cup },
00137 { ANSIESC_ED, bios_handle_ed },
00138 { ANSIESC_SGR, bios_handle_sgr },
00139 { 0, NULL }
00140 };
00141
00142
00143 static struct ansiesc_context bios_ansiesc_ctx = {
00144 .handlers = bios_ansiesc_handlers,
00145 };
00146
00147
00148
00149
00150
00151
00152 static void bios_putchar ( int character ) {
00153 int discard_a, discard_b, discard_c;
00154
00155
00156 character = ansiesc_process ( &bios_ansiesc_ctx, character );
00157 if ( character < 0 )
00158 return;
00159
00160
00161 __asm__ __volatile__ ( REAL_CODE ( "sti\n\t"
00162
00163 "cmpb $0x20, %%al\n\t"
00164 "jb 1f\n\t"
00165
00166 "movw $0x0001, %%cx\n\t"
00167 "movb $0x09, %%ah\n\t"
00168 "int $0x10\n\t"
00169 "\n1:\n\t"
00170
00171 "xorw %%bx, %%bx\n\t"
00172 "movb $0x0e, %%ah\n\t"
00173 "int $0x10\n\t"
00174 "cli\n\t" )
00175 : "=a" ( discard_a ), "=b" ( discard_b ),
00176 "=c" ( discard_c )
00177 : "a" ( character ), "b" ( bios_attr )
00178 : "ebp" );
00179 }
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189 static const char *ansi_input = "";
00190
00191
00192
00193
00194
00195
00196
00197
00198 #define BIOS_KEY_MIN 0x42
00199
00200
00201 #define BIOS_KEY(scancode) ( (scancode) - BIOS_KEY_MIN )
00202
00203
00204 static const char *ansi_sequences[] = {
00205 [ BIOS_KEY ( 0x42 ) ] = "[19~",
00206 [ BIOS_KEY ( 0x47 ) ] = "[H",
00207 [ BIOS_KEY ( 0x48 ) ] = "[A",
00208 [ BIOS_KEY ( 0x4b ) ] = "[D",
00209 [ BIOS_KEY ( 0x4d ) ] = "[C",
00210 [ BIOS_KEY ( 0x4f ) ] = "[F",
00211 [ BIOS_KEY ( 0x50 ) ] = "[B",
00212 [ BIOS_KEY ( 0x53 ) ] = "[3~",
00213 };
00214
00215
00216
00217
00218
00219
00220
00221 static const char * scancode_to_ansi_seq ( unsigned int scancode ) {
00222 unsigned int bios_key = BIOS_KEY ( scancode );
00223
00224 if ( bios_key < ( sizeof ( ansi_sequences ) /
00225 sizeof ( ansi_sequences[0] ) ) ) {
00226 return ansi_sequences[bios_key];
00227 }
00228 DBG ( "Unrecognised BIOS scancode %02x\n", scancode );
00229 return NULL;
00230 }
00231
00232
00233
00234
00235
00236
00237 static int bios_getchar ( void ) {
00238 uint16_t keypress;
00239 unsigned int character;
00240 const char *ansi_seq;
00241
00242
00243 if ( ( character = *ansi_input ) ) {
00244 ansi_input++;
00245 return character;
00246 }
00247
00248
00249 __asm__ __volatile__ ( REAL_CODE ( "sti\n\t"
00250 "int $0x16\n\t"
00251 "cli\n\t" )
00252 : "=a" ( keypress ) : "a" ( 0x1000 ) );
00253 character = ( keypress & 0xff );
00254
00255
00256 if ( character && ( character < 0x80 ) )
00257 return character;
00258
00259
00260 if ( ( ansi_seq = scancode_to_ansi_seq ( keypress >> 8 ) ) ) {
00261
00262 ansi_input = ansi_seq;
00263 return 0x1b;
00264 }
00265
00266 return 0;
00267 }
00268
00269
00270
00271
00272
00273
00274
00275 static int bios_iskey ( void ) {
00276 unsigned int discard_a;
00277 unsigned int flags;
00278
00279
00280 if ( *ansi_input )
00281 return 1;
00282
00283
00284 __asm__ __volatile__ ( REAL_CODE ( "sti\n\t"
00285 "int $0x16\n\t"
00286 "pushfw\n\t"
00287 "popw %w0\n\t"
00288 "cli\n\t" )
00289 : "=r" ( flags ), "=a" ( discard_a )
00290 : "a" ( 0x0100 ) );
00291 return ( ! ( flags & ZF ) );
00292 }
00293
00294 struct console_driver bios_console __console_driver = {
00295 .putchar = bios_putchar,
00296 .getchar = bios_getchar,
00297 .iskey = bios_iskey,
00298 };