Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:09

0001 /**
0002  * @file
0003  *
0004  * @ingroup RTEMSBSPsX8664AMD64EFI
0005  *
0006  * @brief displaying characters on the console
0007  *
0008  * NOTE: This file is copied from arm/raspberrypi BSP.
0009  *       It is only slightly changed to work with EFI GOP.
0010  *       Obvious idea is to refactor whole framebuffer console
0011  *       business shared between various BSPs and move that
0012  *       properly to bsps/shared and reuse.
0013  */
0014 
0015 /**
0016  *
0017  * Copyright (c) 2015 Yang Qiao
0018  * based on work by:
0019  * Copyright (C) 1998  Eric Valette (valette@crf.canon.fr)
0020  *                     Canon Centre Recherche France.
0021  *
0022  *  The license and distribution terms for this file may be
0023  *  found in the file LICENSE in this distribution or at
0024  *  http://www.rtems.org/license/LICENSE.
0025  *
0026  * Till Straumann <strauman@slac.stanford.edu>, 2003/9:
0027  *  - added handling of basic escape sequences (cursor movement
0028  *    and erasing; just enough for the line editor 'libtecla' to
0029  *    work...)
0030  *
0031  */
0032 
0033 #include <bsp.h>
0034 #include <rtems/fb.h>
0035 
0036 #include <efigop.h>
0037 
0038 #include <stdlib.h>
0039 #include <string.h>
0040 #include "font_data.h"
0041 
0042 static void wr_cursor(
0043   int           r,
0044   int           c
0045 )
0046 {
0047   /* dummy function for now */
0048 }
0049 
0050 #define TAB_SPACE 4
0051 #define CONSOLE_BG_COL 0xff
0052 #define CONSOLE_FG_COL 0x00
0053 
0054 static void          *fb_mem = NULL;
0055 static unsigned short maxCol;
0056 static unsigned short maxRow;
0057 static unsigned short bytes_per_pixel;
0058 static unsigned int   bytes_per_line;
0059 static unsigned int   bytes_per_char_line;
0060 static unsigned char  row;
0061 static unsigned char  column;
0062 static unsigned int   nLines;
0063 static uint32_t       fgx, bgx, eorx;
0064 static int            rpi_video_initialized;
0065 
0066 static const int video_font_draw_table32[ 16 ][ 4 ] = {
0067   { 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
0068   { 0x00000000, 0x00000000, 0x00000000, 0x00ffffff },
0069   { 0x00000000, 0x00000000, 0x00ffffff, 0x00000000 },
0070   { 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff },
0071   { 0x00000000, 0x00ffffff, 0x00000000, 0x00000000 },
0072   { 0x00000000, 0x00ffffff, 0x00000000, 0x00ffffff },
0073   { 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000 },
0074   { 0x00000000, 0x00ffffff, 0x00ffffff, 0x00ffffff },
0075   { 0x00ffffff, 0x00000000, 0x00000000, 0x00000000 },
0076   { 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff },
0077   { 0x00ffffff, 0x00000000, 0x00ffffff, 0x00000000 },
0078   { 0x00ffffff, 0x00000000, 0x00ffffff, 0x00ffffff },
0079   { 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000 },
0080   { 0x00ffffff, 0x00ffffff, 0x00000000, 0x00ffffff },
0081   { 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00000000 },
0082   { 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff }
0083 };
0084 
0085 void
0086 rpi_fb_outch( char c );
0087 
0088 void
0089 rpi_video_init( void );
0090 
0091 static void scroll( void )
0092 {
0093   int      i, j;      /* Counters */
0094   uint8_t *pt_scroll, *pt_bitmap;  /* Pointers on the bit-map  */
0095 
0096   pt_bitmap = fb_mem;
0097   j = 0;
0098   pt_bitmap = pt_bitmap + j;
0099   pt_scroll = pt_bitmap + bytes_per_char_line;
0100 
0101   for ( i = j; i < maxRow - 1; i++ ) {
0102     memcpy( pt_bitmap, pt_scroll, bytes_per_char_line );
0103     pt_bitmap = pt_bitmap + bytes_per_char_line;
0104     pt_scroll = pt_bitmap + bytes_per_char_line;
0105   }
0106 
0107   /*
0108    * Blank characters are displayed on the last line.
0109    */
0110   memset( pt_bitmap, CONSOLE_BG_COL, bytes_per_char_line );
0111 }
0112 
0113 static void doCRNL(
0114   int cr,
0115   int nl
0116 )
0117 {
0118   if ( nl ) {
0119     if ( ++row == maxRow ) {
0120       scroll();   /* Scroll the screen now */
0121       row = maxRow - 1;
0122     }
0123 
0124     nLines++;
0125   }
0126 
0127   if ( cr )
0128     column = 0;
0129 
0130   /* Move cursor on the next location  */
0131   if ( cr || nl ) {
0132     wr_cursor( row, column );
0133   }
0134 }
0135 
0136 static void advanceCursor( void )
0137 {
0138   if ( ++column == maxCol )
0139     doCRNL( 1, 1 );
0140   else
0141     wr_cursor( row, column );
0142 }
0143 
0144 static void gotorc(
0145   int r,
0146   int c
0147 )
0148 {
0149   column = c;
0150   row = r;
0151   wr_cursor( row, column );
0152 }
0153 
0154 static void video_drawchars(
0155   int           r,
0156   int           c,
0157   unsigned char ch
0158 )
0159 {
0160   if ( fb_mem == NULL ) {
0161     return;
0162   }
0163 
0164   uint8_t *cdat, *dest, *dest0;
0165   int      rows, offset;
0166 
0167   offset = r * bytes_per_char_line + c * bytes_per_pixel * RPI_FONT_WIDTH;
0168   dest0 = fb_mem + offset;
0169 
0170   /*
0171    * only 32-bit per pixel format is supported for now
0172    */
0173   cdat = rpi_font + ch * RPI_FONT_HEIGHT;
0174 
0175   for ( rows = RPI_FONT_HEIGHT, dest = dest0;
0176         rows--; dest += bytes_per_line ) {
0177     uint8_t bits = *cdat++;
0178 
0179     ( (uint32_t *) dest )[ 0 ] =
0180       ( video_font_draw_table32
0181         [ bits >> 4 ][ 0 ] & eorx ) ^ bgx;
0182     ( (uint32_t *) dest )[ 1 ] =
0183       ( video_font_draw_table32
0184         [ bits >> 4 ][ 1 ] & eorx ) ^ bgx;
0185     ( (uint32_t *) dest )[ 2 ] =
0186       ( video_font_draw_table32
0187         [ bits >> 4 ][ 2 ] & eorx ) ^ bgx;
0188     ( (uint32_t *) dest )[ 3 ] =
0189       ( video_font_draw_table32
0190         [ bits >> 4 ][ 3 ] & eorx ) ^ bgx;
0191 
0192     ( (uint32_t *) dest )[ 4 ] =
0193       ( video_font_draw_table32
0194         [ bits & 15 ][ 0 ] & eorx ) ^ bgx;
0195     ( (uint32_t *) dest )[ 5 ] =
0196       ( video_font_draw_table32
0197         [ bits & 15 ][ 1 ] & eorx ) ^ bgx;
0198     ( (uint32_t *) dest )[ 6 ] =
0199       ( video_font_draw_table32
0200         [ bits & 15 ][ 2 ] & eorx ) ^ bgx;
0201     ( (uint32_t *) dest )[ 7 ] =
0202       ( video_font_draw_table32
0203         [ bits & 15 ][ 3 ] & eorx ) ^ bgx;
0204   }
0205 }
0206 
0207 #define ESC ( (char) 27 )
0208 /* erase current location without moving the cursor */
0209 #define BLANK ( (char) 0x7f )
0210 
0211 static void videoPutChar( char ch )
0212 {
0213   switch ( ch ) {
0214     case '\b': {
0215       if ( column )
0216         column--;
0217 
0218       /* Move cursor on the previous location  */
0219       wr_cursor( row, column );
0220       return;
0221     }
0222     case '\t': {
0223       int i;
0224 
0225       i = TAB_SPACE - ( column & ( TAB_SPACE - 1 ) );
0226 
0227       while ( i-- ) {
0228 
0229         video_drawchars( row, column, ' ' );
0230         column += 1;
0231 
0232         if ( column >= maxCol ) {
0233           doCRNL( 1, 1 );
0234           return;
0235         }
0236       }
0237 
0238       wr_cursor( row, column );
0239 
0240       return;
0241     }
0242     case '\n': {
0243       doCRNL( 0, 1 );
0244       return;
0245     }
0246     case 7:   {     /* Bell code must be inserted here */
0247       return;
0248     }
0249     case '\r': {
0250       doCRNL( 1, 0 );
0251       return;
0252     }
0253     case BLANK: {
0254       video_drawchars( row, column, ' ' );
0255 
0256       wr_cursor( row, column );
0257 
0258       return;
0259     }
0260     default: {
0261       // *pt_bitmap = (unsigned char)ch | attribute;
0262       video_drawchars( row, column, ch );
0263       advanceCursor();
0264       return;
0265     }
0266   }
0267 }
0268 
0269 /* trivial state machine to handle escape sequences:
0270  *
0271  *                    ---------------------------------
0272  *                   |                                 |
0273  *                   |                                 |
0274  * KEY:        esc   V    [          DCABHKJ       esc |
0275  * STATE:   0 -----> 27 -----> '[' ----------> -1 -----
0276  *          ^\        \          \               \
0277  * KEY:     | \other   \ other    \ other         \ other
0278  *           <-------------------------------------
0279  *
0280  * in state '-1', the DCABHKJ cases are handled
0281  *
0282  * (cursor motion and screen clearing)
0283  */
0284 
0285 #define DONE ( -1 )
0286 
0287 static int handleEscape(
0288   int  oldState,
0289   char ch
0290 )
0291 {
0292   int rval = 0;
0293   int ro, co;
0294 
0295   switch ( oldState ) {
0296     case DONE:  /*  means the previous char terminated an ESC sequence... */
0297     case 0:
0298 
0299       if ( 27 == ch ) {
0300         rval = 27;   /* START of an ESC sequence */
0301       }
0302 
0303       break;
0304 
0305     case 27:
0306 
0307       if ( '[' == ch ) {
0308         rval = ch;  /* received ESC '[', so far */
0309       } else {
0310         /* dump suppressed 'ESC'; outch will append the char */
0311         videoPutChar( ESC );
0312       }
0313 
0314       break;
0315 
0316     case '[':
0317       /* handle 'ESC' '[' sequences here */
0318       ro = row;
0319       co = column;
0320       rval = DONE; /* done */
0321 
0322       switch ( ch ) {
0323         case 'D': /* left */
0324 
0325           if ( co > 0 )
0326             co--;
0327 
0328           break;
0329         case 'C': /* right */
0330 
0331           if ( co < maxCol )
0332             co++;
0333 
0334           break;
0335         case 'A': /* up    */
0336 
0337           if ( ro > 0 )
0338             ro--;
0339 
0340           break;
0341         case 'B': /* down */
0342 
0343           if ( ro < maxRow )
0344             ro++;
0345 
0346           break;
0347         case 'H': /* home */
0348           ro = co = 0;
0349           break;
0350         case 'K': /* clear to end of line */
0351 
0352           while ( column < maxCol - 1 )
0353             videoPutChar( ' ' );
0354 
0355           videoPutChar( BLANK );
0356           break;
0357         case 'J':     /* clear to end of screen */
0358 
0359           while ( ( ( row < maxRow - 1 ) || ( column < maxCol - 1 ) ) )
0360             videoPutChar( ' ' );
0361 
0362           videoPutChar( BLANK );
0363           break;
0364         default:
0365           videoPutChar( ESC );
0366           videoPutChar( '[' );
0367           /* DONT move the cursor */
0368           ro = -1;
0369           rval = 0;
0370           break;
0371       }
0372 
0373       // /* reset cursor */
0374       if ( ro >= 0 )
0375         gotorc( ro, co );
0376 
0377     default:
0378       break;
0379   }
0380 
0381   return rval;
0382 }
0383 
0384 static void clear_screen( void )
0385 {
0386   int i, j;
0387 
0388   for ( j = 0; j < maxRow; j++ ) {
0389     for ( i = 0; i < maxCol; i++ ) {
0390       videoPutChar( ' ' );
0391     }
0392   }
0393 
0394   column = 0;
0395   row = 0;
0396 }
0397 
0398 void rpi_fb_outch( char c )
0399 {
0400   static int escaped = 0;
0401 
0402   if ( !( escaped = handleEscape( escaped, c ) ) ) {
0403     if ( '\n' == c )
0404       videoPutChar( '\r' );
0405 
0406     videoPutChar( c );
0407   }
0408 }
0409 
0410 void rpi_video_init( void )
0411 {
0412   struct fb_var_screeninfo fb_var_info;
0413   struct fb_fix_screeninfo fb_fix_info;
0414   rpi_get_var_screen_info( &fb_var_info );
0415   rpi_get_fix_screen_info( &fb_fix_info );
0416   maxCol = fb_var_info.xres / RPI_FONT_WIDTH;
0417   maxRow = fb_var_info.yres / RPI_FONT_HEIGHT;
0418   bytes_per_pixel = fb_var_info.bits_per_pixel / 8;
0419   bytes_per_line = bytes_per_pixel * fb_var_info.xres;
0420   bytes_per_char_line = RPI_FONT_HEIGHT * bytes_per_line;
0421   fb_mem = RTEMS_DEVOLATILE( void *, fb_fix_info.smem_start );
0422   column = 0;
0423   row = 0;
0424   nLines = 0;
0425   fgx = ( CONSOLE_FG_COL << 24 ) |
0426         ( CONSOLE_FG_COL << 16 ) |
0427         ( CONSOLE_FG_COL << 8 ) |
0428         CONSOLE_FG_COL;
0429   bgx = ( CONSOLE_BG_COL << 24 ) |
0430         ( CONSOLE_BG_COL << 16 ) |
0431         ( CONSOLE_BG_COL << 8 ) |
0432         CONSOLE_BG_COL;
0433   eorx = fgx ^ bgx;
0434   clear_screen();
0435   rpi_video_initialized = 1;
0436 }
0437 /* for old DOS compatibility n-curses type of applications */
0438 void gotoxy(
0439   int x,
0440   int y
0441 );
0442 int whereX( void );
0443 int whereY( void );
0444 
0445 void gotoxy(
0446   int x,
0447   int y
0448 )
0449 {
0450   gotorc( y, x );
0451 }
0452 
0453 int whereX( void )
0454 {
0455   return row;
0456 }
0457 
0458 int whereY( void )
0459 {
0460   return column;
0461 }