david/ipxe
david
/
ipxe
Archived
1
0
Fork 0

[vesafb] Return meaningful error when no suitable mode is found

Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
Michael Brown 2013-11-28 12:12:05 +00:00
parent 405416e4c4
commit 00bb19257f
1 changed files with 75 additions and 44 deletions

View File

@ -70,14 +70,14 @@ struct console_driver vesafb_console __console_driver;
struct vesafb { struct vesafb {
/** Frame buffer console */ /** Frame buffer console */
struct fbcon fbcon; struct fbcon fbcon;
/** Physical start address */
physaddr_t start;
/** Pixel geometry */ /** Pixel geometry */
struct fbcon_geometry pixel; struct fbcon_geometry pixel;
/** Colour mapping */ /** Colour mapping */
struct fbcon_colour_map map; struct fbcon_colour_map map;
/** Font definition */ /** Font definition */
struct fbcon_font font; struct fbcon_font font;
/** Total length */
size_t len;
/** Saved VGA mode */ /** Saved VGA mode */
uint8_t saved_mode; uint8_t saved_mode;
}; };
@ -215,12 +215,10 @@ static int vesafb_mode_list ( uint16_t **mode_numbers ) {
* *
* @v mode_number Mode number * @v mode_number Mode number
* @v mode Mode information * @v mode Mode information
* @v pixbuf Background picture (if any)
* @ret rc Return status code * @ret rc Return status code
*/ */
static int vesafb_set_mode ( unsigned int mode_number, static int vesafb_set_mode ( unsigned int mode_number,
struct vbe_mode_info *mode, struct vbe_mode_info *mode ) {
struct pixel_buffer *pixbuf ) {
uint16_t status; uint16_t status;
int rc; int rc;
@ -236,6 +234,7 @@ static int vesafb_set_mode ( unsigned int mode_number,
} }
/* Record mode parameters */ /* Record mode parameters */
vesafb.start = mode->phys_base_ptr;
vesafb.pixel.width = mode->x_resolution; vesafb.pixel.width = mode->x_resolution;
vesafb.pixel.height = mode->y_resolution; vesafb.pixel.height = mode->y_resolution;
vesafb.pixel.len = ( ( mode->bits_per_pixel + 7 ) / 8 ); vesafb.pixel.len = ( ( mode->bits_per_pixel + 7 ) / 8 );
@ -251,38 +250,26 @@ static int vesafb_set_mode ( unsigned int mode_number,
vesafb.map.green_lsb = mode->green_field_position; vesafb.map.green_lsb = mode->green_field_position;
vesafb.map.blue_lsb = mode->blue_field_position; vesafb.map.blue_lsb = mode->blue_field_position;
/* Get font data */
vesafb_font();
/* Initialise frame buffer console */
fbcon_init ( &vesafb.fbcon, phys_to_user ( mode->phys_base_ptr ),
&vesafb.pixel, &vesafb.map, &vesafb.font, pixbuf );
return 0; return 0;
} }
/** /**
* Select and set video mode * Select and set video mode
* *
* @v mode_numbers Mode number list (terminated with VBE_MODE_END)
* @v min_width Minimum required width (in pixels) * @v min_width Minimum required width (in pixels)
* @v min_height Minimum required height (in pixels) * @v min_height Minimum required height (in pixels)
* @v min_bpp Minimum required colour depth (in bits per pixel) * @v min_bpp Minimum required colour depth (in bits per pixel)
* @v pixbuf Background picture (if any)
* @ret rc Return status code * @ret rc Return status code
*/ */
static int vesafb_select_mode ( unsigned int min_width, unsigned int min_height, static int vesafb_select_mode ( const uint16_t *mode_numbers,
unsigned int min_bpp, unsigned int min_width, unsigned int min_height,
struct pixel_buffer *pixbuf ) { unsigned int min_bpp ) {
struct vbe_mode_info *mode = &vbe_buf.mode; struct vbe_mode_info *mode = &vbe_buf.mode;
uint16_t *mode_numbers;
uint16_t mode_number; uint16_t mode_number;
uint16_t status; uint16_t status;
int rc; int rc;
/* Get VESA mode list */
if ( ( rc = vesafb_mode_list ( &mode_numbers ) ) != 0 )
goto err_mode_list;
/* Find the first suitable mode */ /* Find the first suitable mode */
while ( ( mode_number = *(mode_numbers++) ) != VBE_MODE_END ) { while ( ( mode_number = *(mode_numbers++) ) != VBE_MODE_END ) {
@ -339,20 +326,77 @@ static int vesafb_select_mode ( unsigned int min_width, unsigned int min_height,
} }
/* Select this mode */ /* Select this mode */
if ( ( rc = vesafb_set_mode ( mode_number, mode, if ( ( rc = vesafb_set_mode ( mode_number, mode ) ) != 0 )
pixbuf ) ) != 0 ) { return rc;
goto err_set_mode;
}
break; return 0;
} }
err_set_mode: DBGC ( &vbe_buf, "VESAFB found no suitable mode\n" );
return -ENOENT;
}
/**
* Initialise VESA frame buffer
*
* @v min_width Minimum required width (in pixels)
* @v min_height Minimum required height (in pixels)
* @v min_bpp Minimum required colour depth (in bits per pixel)
* @v pixbuf Background picture (if any)
* @ret rc Return status code
*/
static int vesafb_init ( unsigned int min_width, unsigned int min_height,
unsigned int min_bpp, struct pixel_buffer *pixbuf ) {
uint32_t discard_b;
uint16_t *mode_numbers;
int rc;
/* Record current VGA mode */
__asm__ __volatile__ ( REAL_CODE ( "int $0x10" )
: "=a" ( vesafb.saved_mode ), "=b" ( discard_b )
: "a" ( VBE_GET_VGA_MODE ) );
DBGC ( &vbe_buf, "VESAFB saved VGA mode %#02x\n", vesafb.saved_mode );
/* Get VESA mode list */
if ( ( rc = vesafb_mode_list ( &mode_numbers ) ) != 0 )
goto err_mode_list;
/* Select and set mode */
if ( ( rc = vesafb_select_mode ( mode_numbers, min_width, min_height,
min_bpp ) ) != 0 )
goto err_select_mode;
/* Get font data */
vesafb_font();
/* Initialise frame buffer console */
fbcon_init ( &vesafb.fbcon, phys_to_user ( vesafb.start ),
&vesafb.pixel, &vesafb.map, &vesafb.font, pixbuf );
err_select_mode:
free ( mode_numbers ); free ( mode_numbers );
err_mode_list: err_mode_list:
return rc; return rc;
} }
/**
* Finalise VESA frame buffer
*
*/
static void vesafb_fini ( void ) {
uint32_t discard_a;
/* Finalise frame buffer console */
fbcon_fini ( &vesafb.fbcon );
/* Restore VGA mode */
__asm__ __volatile__ ( REAL_CODE ( "int $0x10" )
: "=a" ( discard_a )
: "a" ( VBE_SET_VGA_MODE | vesafb.saved_mode ) );
DBGC ( &vbe_buf, "VESAFB restored VGA mode %#02x\n",
vesafb.saved_mode );
}
/** /**
* Print a character to current cursor position * Print a character to current cursor position
* *
@ -370,37 +414,24 @@ static void vesafb_putchar ( int character ) {
* @ret rc Return status code * @ret rc Return status code
*/ */
static int vesafb_configure ( struct console_configuration *config ) { static int vesafb_configure ( struct console_configuration *config ) {
uint32_t discard_a;
uint32_t discard_b;
int rc; int rc;
/* Reset console, if applicable */ /* Reset console, if applicable */
if ( ! vesafb_console.disabled ) { if ( ! vesafb_console.disabled ) {
fbcon_fini ( &vesafb.fbcon ); vesafb_fini();
__asm__ __volatile__ ( REAL_CODE ( "int $0x10" )
: "=a" ( discard_a )
: "a" ( VBE_SET_VGA_MODE |
vesafb.saved_mode ) );
DBGC ( &vbe_buf, "VESAFB restored VGA mode %#02x\n",
vesafb.saved_mode );
bios_console.disabled &= ~CONSOLE_DISABLED_OUTPUT; bios_console.disabled &= ~CONSOLE_DISABLED_OUTPUT;
} }
vesafb_console.disabled = CONSOLE_DISABLED; vesafb_console.disabled = CONSOLE_DISABLED;
/* Record current video mode */
__asm__ __volatile__ ( REAL_CODE ( "int $0x10" )
: "=a" ( vesafb.saved_mode ), "=b" ( discard_b )
: "a" ( VBE_GET_VGA_MODE ) );
/* Do nothing more unless we have a usable configuration */ /* Do nothing more unless we have a usable configuration */
if ( ( config == NULL ) || if ( ( config == NULL ) ||
( config->width == 0 ) || ( config->height == 0 ) ) { ( config->width == 0 ) || ( config->height == 0 ) ) {
return 0; return 0;
} }
/* Try to select an appropriate mode */ /* Initialise VESA frame buffer */
if ( ( rc = vesafb_select_mode ( config->width, config->height, if ( ( rc = vesafb_init ( config->width, config->height, config->bpp,
config->bpp, config->pixbuf ) ) != 0 ) config->pixbuf ) ) != 0 )
return rc; return rc;
/* Mark console as enabled */ /* Mark console as enabled */