summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/arch/x86/interface/pcbios/vesafb.c101
-rw-r--r--src/core/fbcon.c72
-rw-r--r--src/hci/commands/console_cmd.c2
-rw-r--r--src/include/ipxe/console.h2
4 files changed, 109 insertions, 68 deletions
diff --git a/src/arch/x86/interface/pcbios/vesafb.c b/src/arch/x86/interface/pcbios/vesafb.c
index 50e485852..9cdffd32c 100644
--- a/src/arch/x86/interface/pcbios/vesafb.c
+++ b/src/arch/x86/interface/pcbios/vesafb.c
@@ -422,34 +422,36 @@ static void vesafb_restore ( void ) {
*/
static int vesafb_init ( struct console_configuration *config ) {
uint32_t discard_b;
- uint16_t *mode_numbers;
+ uint16_t *mode_numbers = NULL;
int mode_number;
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 mode */
- if ( ( mode_number = vesafb_select_mode ( mode_numbers, config->width,
- config->height,
- config->depth ) ) < 0 ) {
- rc = mode_number;
- goto err_select_mode;
- }
+ if ( ! config->lazy_update ) {
+ /* 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 mode */
+ if ( ( mode_number = vesafb_select_mode ( mode_numbers, config->width,
+ config->height,
+ config->depth ) ) < 0 ) {
+ rc = mode_number;
+ goto err_select_mode;
+ }
- /* Set mode */
- if ( ( rc = vesafb_set_mode ( mode_number ) ) != 0 )
- goto err_set_mode;
+ /* Set mode */
+ if ( ( rc = vesafb_set_mode ( mode_number ) ) != 0 )
+ goto err_set_mode;
- /* Get font data */
- vesafb_font();
+ /* Get font data */
+ vesafb_font();
+ }
/* Initialise frame buffer console */
if ( ( rc = fbcon_init ( &vesafb.fbcon, phys_to_user ( vesafb.start ),
@@ -502,17 +504,40 @@ static void vesafb_putchar ( int character ) {
static int vesafb_configure ( struct console_configuration *config ) {
int rc;
- /* Reset console, if applicable */
- if ( ! vesafb_console.disabled ) {
- vesafb_fini();
- bios_console.disabled &= ~CONSOLE_DISABLED_OUTPUT;
- ansicol_reset_magic();
+ if ( config == NULL ) {
+ return 0;
+ }
+ if ( config->lazy_update ) {
+ if ( vesafb_console.disabled ) {
+ /* --update mode with disabled console -> nothing to do */
+ return 0;
+ }
+ /* No width/height given, use current so we can update the border */
+ if ( ( config->width == 0 ) || ( config->height == 0 ) ) {
+ if ( ( vesafb.pixel.width == 0 ) || ( vesafb.pixel.height == 0 ) ) {
+ return -EINVAL;
+ }
+ config->width = vesafb.pixel.width;
+ config->height = vesafb.pixel.height;
+ } else {
+ /* Otherwise make sure the new dimensions match the old ones */
+ if ( ( vesafb.pixel.width != config->width ) ||
+ ( vesafb.pixel.height != config->height ) ) {
+ return -EINVAL;
+ }
+ }
+ } else {
+ /* Reset console, if applicable */
+ if ( ! vesafb_console.disabled ) {
+ vesafb_fini();
+ bios_console.disabled &= ~CONSOLE_DISABLED_OUTPUT;
+ ansicol_reset_magic();
+ }
+ vesafb_console.disabled = CONSOLE_DISABLED;
}
- vesafb_console.disabled = CONSOLE_DISABLED;
/* Do nothing more unless we have a usable configuration */
- if ( ( config == NULL ) ||
- ( config->width == 0 ) || ( config->height == 0 ) ) {
+ if ( ( config->width == 0 ) || ( config->height == 0 ) ) {
return 0;
}
@@ -520,13 +545,15 @@ static int vesafb_configure ( struct console_configuration *config ) {
if ( ( rc = vesafb_init ( config ) ) != 0 )
return rc;
- /* Mark console as enabled */
- vesafb_console.disabled = 0;
- bios_console.disabled |= CONSOLE_DISABLED_OUTPUT;
+ if ( ! config->lazy_update ) {
+ /* Mark console as enabled */
+ vesafb_console.disabled = 0;
+ bios_console.disabled |= CONSOLE_DISABLED_OUTPUT;
- /* Set magic colour to transparent if we have a background picture */
- if ( config->pixbuf )
- ansicol_set_magic_transparent();
+ /* Set magic colour to transparent if we have a background picture */
+ if ( config->pixbuf )
+ ansicol_set_magic_transparent();
+ }
return 0;
}
diff --git a/src/core/fbcon.c b/src/core/fbcon.c
index 44a56e105..f64bab7ce 100644
--- a/src/core/fbcon.c
+++ b/src/core/fbcon.c
@@ -520,6 +520,9 @@ static int fbcon_picture_init ( struct fbcon *fbcon,
/* Allocate buffer */
len = ( pixel->height * pixel->stride );
+ if ( picture->start ) {
+ ufree( picture->start );
+ }
picture->start = umalloc ( len );
if ( ! picture->start ) {
DBGC ( fbcon, "FBCON %p could not allocate %zd bytes for "
@@ -595,21 +598,23 @@ int fbcon_init ( struct fbcon *fbcon, userptr_t start,
unsigned int bottom;
int rc;
- /* Initialise data structure */
- memset ( fbcon, 0, sizeof ( *fbcon ) );
- fbcon->start = start;
- fbcon->pixel = pixel;
- assert ( pixel->len <= sizeof ( uint32_t ) );
- fbcon->map = map;
- fbcon->font = font;
- fbcon->ctx.handlers = fbcon_ansiesc_handlers;
- fbcon->show_cursor = 1;
-
- /* Derive overall length */
- fbcon->len = ( pixel->height * pixel->stride );
- DBGC ( fbcon, "FBCON %p at [%08lx,%08lx)\n", fbcon,
- user_to_phys ( fbcon->start, 0 ),
- user_to_phys ( fbcon->start, fbcon->len ) );
+ if ( ! config->lazy_update ) {
+ /* Initialise data structure */
+ memset ( fbcon, 0, sizeof ( *fbcon ) );
+ fbcon->start = start;
+ fbcon->pixel = pixel;
+ assert ( pixel->len <= sizeof ( uint32_t ) );
+ fbcon->map = map;
+ fbcon->font = font;
+ fbcon->ctx.handlers = fbcon_ansiesc_handlers;
+ fbcon->show_cursor = 1;
+
+ /* Derive overall length */
+ fbcon->len = ( pixel->height * pixel->stride );
+ DBGC ( fbcon, "FBCON %p at [%08lx,%08lx)\n", fbcon,
+ user_to_phys ( fbcon->start, 0 ),
+ user_to_phys ( fbcon->start, fbcon->len ) );
+ }
/* Calculate margin. If the actual screen size is larger than
* the requested screen size, then update the margins so that
@@ -664,27 +669,32 @@ int fbcon_init ( struct fbcon *fbcon, userptr_t start,
fbcon->margin.top,
( fbcon->pixel->height - fbcon->margin.bottom ) );
- /* Set default colours */
- fbcon_set_default_foreground ( fbcon );
- fbcon_set_default_background ( fbcon );
+ if ( ! config->lazy_update ) {
+ /* Set default colours */
+ fbcon_set_default_foreground ( fbcon );
+ fbcon_set_default_background ( fbcon );
+
+ /* Allocate and initialise stored character array */
+ fbcon->text.start = umalloc ( fbcon->character.width *
+ fbcon->character.height *
+ sizeof ( struct fbcon_text_cell ) );
+ if ( ! fbcon->text.start ) {
+ rc = -ENOMEM;
+ goto err_text;
+ }
+ fbcon_clear ( fbcon, 0 );
- /* Allocate and initialise stored character array */
- fbcon->text.start = umalloc ( fbcon->character.width *
- fbcon->character.height *
- sizeof ( struct fbcon_text_cell ) );
- if ( ! fbcon->text.start ) {
- rc = -ENOMEM;
- goto err_text;
+ /* Set framebuffer to all black (including margins) */
+ memset_user ( fbcon->start, 0, 0, fbcon->len );
+ } else {
+ fbcon_clear ( fbcon, 0 );
}
- fbcon_clear ( fbcon, 0 );
-
- /* Set framebuffer to all black (including margins) */
- memset_user ( fbcon->start, 0, 0, fbcon->len );
/* Generate pixel buffer from background image, if applicable */
if ( config->pixbuf &&
- ( ( rc = fbcon_picture_init ( fbcon, config->pixbuf ) ) != 0 ) )
- goto err_picture;
+ ( ( rc = fbcon_picture_init ( fbcon, config->pixbuf ) ) != 0 ) &&
+ ( ! config->lazy_update ) )
+ goto err_picture; /* Keep going w/o background in lazy_update mode */
/* Draw background picture (including margins), if applicable */
if ( fbcon->picture.start ) {
diff --git a/src/hci/commands/console_cmd.c b/src/hci/commands/console_cmd.c
index ba472b9f6..bd5647261 100644
--- a/src/hci/commands/console_cmd.c
+++ b/src/hci/commands/console_cmd.c
@@ -70,6 +70,8 @@ static struct option_descriptor console_opts[] = {
struct console_options, picture, parse_string ),
OPTION_DESC ( "keep", 'k', no_argument,
struct console_options, keep, parse_flag ),
+ OPTION_DESC ( "update", 'u', no_argument,
+ struct console_options, config.lazy_update, parse_flag ),
};
/** "console" command descriptor */
diff --git a/src/include/ipxe/console.h b/src/include/ipxe/console.h
index 1b764aaca..ca8093a73 100644
--- a/src/include/ipxe/console.h
+++ b/src/include/ipxe/console.h
@@ -38,6 +38,8 @@ struct console_configuration {
unsigned int bottom;
/** Background picture, if any */
struct pixel_buffer *pixbuf;
+ /** Update mode: Don't re-init vesa mode, just update margins and bg image */
+ int lazy_update;
};
/**