diff --git a/src/arch/i386/interface/pcbios/vesafb.c b/src/arch/i386/interface/pcbios/vesafb.c index 9cf2bf29e..4742f956b 100644 --- a/src/arch/i386/interface/pcbios/vesafb.c +++ b/src/arch/i386/interface/pcbios/vesafb.c @@ -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; } /** diff --git a/src/core/fbcon.c b/src/core/fbcon.c index 6d8b0086d..90139c709 100644 --- a/src/core/fbcon.c +++ b/src/core/fbcon.c @@ -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, diff --git a/src/include/ipxe/fbcon.h b/src/include/ipxe/fbcon.h index d442bb918..7837845ed 100644 --- a/src/include/ipxe/fbcon.h +++ b/src/include/ipxe/fbcon.h @@ -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 *