diff options
| -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; }; /** |
