]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[fbcon] Allow character height to be selected at runtime
authorMichael Brown <mcb30@ipxe.org>
Wed, 14 Oct 2015 19:42:42 +0000 (20:42 +0100)
committerMichael Brown <mcb30@ipxe.org>
Wed, 14 Oct 2015 21:16:40 +0000 (22:16 +0100)
Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/arch/i386/interface/pcbios/vesafb.c
src/core/fbcon.c
src/include/ipxe/fbcon.h

index 9cf2bf29ec20c42aa1480ca375216afebb37799a..4742f956b27940360e114f041a0e2e4636b30aba 100644 (file)
@@ -66,6 +66,9 @@ struct console_driver bios_console __attribute__ (( weak ));
 #define CONSOLE_VESAFB ( CONSOLE_USAGE_ALL & ~CONSOLE_USAGE_LOG )
 #endif
 
+/** Character height */
+#define VESAFB_CHAR_HEIGHT 16
+
 /** Font corresponding to selected character width and height */
 #define VESAFB_FONT VBE_FONT_8x16
 
@@ -86,6 +89,8 @@ struct vesafb {
        struct fbcon_colour_map map;
        /** Font definition */
        struct fbcon_font font;
+       /** Character glyphs */
+       struct segoff glyphs;
        /** Saved VGA mode */
        uint8_t saved_mode;
 };
@@ -118,12 +123,24 @@ static int vesafb_rc ( unsigned int status ) {
        return ( code ? -EIO_VBE ( code ) : 0 );
 }
 
+/**
+ * Get character glyph
+ *
+ * @v character                Character
+ * @v glyph            Character glyph to fill in
+ */
+static void vesafb_glyph ( unsigned int character, uint8_t *glyph ) {
+       size_t offset = ( character * VESAFB_CHAR_HEIGHT );
+
+       copy_from_real ( glyph, vesafb.glyphs.segment,
+                        ( vesafb.glyphs.offset + offset ), VESAFB_CHAR_HEIGHT);
+}
+
 /**
  * Get font definition
  *
  */
 static void vesafb_font ( void ) {
-       struct segoff font;
 
        /* Get font information
         *
@@ -144,13 +161,14 @@ static void vesafb_font ( void ) {
                                           "movw %%es, %%cx\n\t"
                                           "movw %%bp, %%dx\n\t"
                                           "popw %%bp\n\t" /* gcc bug */ )
-                              : "=c" ( font.segment ),
-                                "=d" ( font.offset )
+                              : "=c" ( vesafb.glyphs.segment ),
+                                "=d" ( vesafb.glyphs.offset )
                               : "a" ( VBE_GET_FONT ),
                                 "b" ( VESAFB_FONT ) );
        DBGC ( &vbe_buf, "VESAFB has font %04x at %04x:%04x\n",
-              VESAFB_FONT, font.segment, font.offset );
-       vesafb.font.start = real_to_user ( font.segment, font.offset );
+              VESAFB_FONT, vesafb.glyphs.segment, vesafb.glyphs.offset );
+       vesafb.font.height = VESAFB_CHAR_HEIGHT;
+       vesafb.font.glyph = vesafb_glyph;
 }
 
 /**
index 6d8b0086dcfa7e1a3e90445c4c6cb991c73e46d7..90139c709a8c73118a3ea8d1937c774371e44103 100644 (file)
@@ -156,7 +156,7 @@ static void fbcon_store ( struct fbcon *fbcon, struct fbcon_text_cell *cell,
  */
 static void fbcon_draw ( struct fbcon *fbcon, struct fbcon_text_cell *cell,
                         unsigned int xpos, unsigned int ypos ) {
-       struct fbcon_font_glyph glyph;
+       uint8_t glyph[fbcon->font->height];
        size_t offset;
        size_t pixel_len;
        size_t skip_len;
@@ -167,9 +167,7 @@ static void fbcon_draw ( struct fbcon *fbcon, struct fbcon_text_cell *cell,
        void *src;
 
        /* Get font character */
-       copy_from_user ( &glyph, fbcon->font->start,
-                        ( cell->character * sizeof ( glyph ) ),
-                        sizeof ( glyph ) );
+       fbcon->font->glyph ( cell->character, glyph );
 
        /* Calculate pixel geometry */
        offset = ( fbcon->indent +
@@ -182,7 +180,7 @@ static void fbcon_draw ( struct fbcon *fbcon, struct fbcon_text_cell *cell,
        transparent = ( cell->background == FBCON_TRANSPARENT );
 
        /* Draw character rows */
-       for ( row = 0 ; row < FBCON_CHAR_HEIGHT ; row++ ) {
+       for ( row = 0 ; row < fbcon->font->height ; row++ ) {
 
                /* Draw background picture, if applicable */
                if ( transparent ) {
@@ -197,7 +195,7 @@ static void fbcon_draw ( struct fbcon *fbcon, struct fbcon_text_cell *cell,
                }
 
                /* Draw character row */
-               for ( column = FBCON_CHAR_WIDTH, bitmask = glyph.bitmask[row] ;
+               for ( column = FBCON_CHAR_WIDTH, bitmask = glyph[row] ;
                      column ; column--, bitmask <<= 1, offset += pixel_len ) {
                        if ( bitmask & 0x80 ) {
                                src = &cell->foreground;
@@ -614,7 +612,8 @@ int fbcon_init ( struct fbcon *fbcon, userptr_t start,
        /* Expand margin to accommodate whole characters */
        width = ( pixel->width - margin->left - margin->right );
        height = ( pixel->height - margin->top - margin->bottom );
-       if ( ( width < FBCON_CHAR_WIDTH ) || ( height < FBCON_CHAR_HEIGHT ) ) {
+       if ( ( width < FBCON_CHAR_WIDTH ) ||
+            ( height < ( ( int ) font->height ) ) ) {
                DBGC ( fbcon, "FBCON %p has unusable character area "
                       "[%d-%d),[%d-%d)\n", fbcon,
                       margin->left, ( pixel->width - margin->right ),
@@ -623,7 +622,7 @@ int fbcon_init ( struct fbcon *fbcon, userptr_t start,
                goto err_margin;
        }
        xgap = ( width % FBCON_CHAR_WIDTH );
-       ygap = ( height % FBCON_CHAR_HEIGHT );
+       ygap = ( height % font->height );
        fbcon->margin.left = ( margin->left + ( xgap / 2 ) );
        fbcon->margin.top = ( margin->top + ( ygap / 2 ) );
        fbcon->margin.right = ( margin->right + ( xgap - ( xgap / 2 ) ) );
@@ -633,9 +632,9 @@ int fbcon_init ( struct fbcon *fbcon, userptr_t start,
 
        /* Derive character geometry from pixel geometry */
        fbcon->character.width = ( width / FBCON_CHAR_WIDTH );
-       fbcon->character.height = ( height / FBCON_CHAR_HEIGHT );
+       fbcon->character.height = ( height / font->height );
        fbcon->character.len = ( pixel->len * FBCON_CHAR_WIDTH );
-       fbcon->character.stride = ( pixel->stride * FBCON_CHAR_HEIGHT );
+       fbcon->character.stride = ( pixel->stride * font->height );
        DBGC ( fbcon, "FBCON %p is pixel %dx%d, char %dx%d at "
               "[%d-%d),[%d-%d)\n", fbcon, fbcon->pixel->width,
               fbcon->pixel->height, fbcon->character.width,
index d442bb9180a14cfb89b975ad8d7a804b2dcc1e84..7837845ed99093824f6da3bc6ec7025a8181b832 100644 (file)
@@ -18,9 +18,6 @@ struct pixel_buffer;
 /** Character width, in pixels */
 #define FBCON_CHAR_WIDTH 9
 
-/** Character height, in pixels */
-#define FBCON_CHAR_HEIGHT 16
-
 /** Bold colour modifier (RGB value) */
 #define FBCON_BOLD 0x555555
 
@@ -30,14 +27,21 @@ struct pixel_buffer;
 /** A font glyph */
 struct fbcon_font_glyph {
        /** Row bitmask */
-       uint8_t bitmask[FBCON_CHAR_HEIGHT];
-} __attribute__ (( packed ));
+       uint8_t bitmask[0];
+};
 
 /** A font definition */
 struct fbcon_font {
-       /** Character glyphs */
-       userptr_t start;
-} __attribute__ (( packed ));
+       /** Character height (in pixels) */
+       unsigned int height;
+       /**
+        * Get character glyph
+        *
+        * @v character         Character
+        * @v glyph             Character glyph to fill in
+        */
+       void ( * glyph ) ( unsigned int character, uint8_t *glyph );
+};
 
 /** A frame buffer geometry
  *