diff options
| author | Simon Rettberg | 2018-05-28 15:33:56 +0200 |
|---|---|---|
| committer | Simon Rettberg | 2018-05-28 15:45:25 +0200 |
| commit | 85b64c16424ce690ba7f640c2f0bde6e70295112 (patch) | |
| tree | 5043b7eede0364ff48be6859a1d31298e4e36bd6 | |
| parent | [icplus] Add driver for IC+ network card (diff) | |
| download | ipxe-85b64c16424ce690ba7f640c2f0bde6e70295112.tar.gz ipxe-85b64c16424ce690ba7f640c2f0bde6e70295112.tar.xz ipxe-85b64c16424ce690ba7f640c2f0bde6e70295112.zip | |
[console] Add option to update margins and bg-image of vesa mode console
Adding --update to the console call will prevent the vesa mode from
being initialized again. The existing mode will be reused. This makes
it possible to quickly update the background image or console margins
without ugly flickering.
| -rw-r--r-- | src/arch/x86/interface/pcbios/vesafb.c | 101 | ||||
| -rw-r--r-- | src/core/fbcon.c | 72 | ||||
| -rw-r--r-- | src/hci/commands/console_cmd.c | 2 | ||||
| -rw-r--r-- | src/include/ipxe/console.h | 2 |
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; }; /** |
