diff options
Diffstat (limited to 'src/interface')
| -rw-r--r-- | src/interface/efi/efi_entropy.c | 27 | ||||
| -rw-r--r-- | src/interface/efi/efi_fbcon.c | 157 |
2 files changed, 117 insertions, 67 deletions
diff --git a/src/interface/efi/efi_entropy.c b/src/interface/efi/efi_entropy.c index 2a2fc9054..2dd231b22 100644 --- a/src/interface/efi/efi_entropy.c +++ b/src/interface/efi/efi_entropy.c @@ -30,6 +30,11 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include <ipxe/efi/efi.h> #include <ipxe/efi/Protocol/Rng.h> +#if defined(__i386) || defined(__x86_64) +#include <ipxe/cpuid.h> +static char have_hwrnd = 0; +#endif + /** @file * * EFI entropy source @@ -120,6 +125,28 @@ static int efi_entropy_tick ( void ) { EFI_STATUS efirc; int rc; +#if defined(__i386) || defined(__x86_64) + if ( have_hwrnd == 0 ) { + struct x86_features features; + x86_features( &features ); + if ( features.intel.ecx & ( 1 << 30 ) ) { + have_hwrnd = 1; + } else { + have_hwrnd = 2; + } + DBGC( &tick, "Have RDRAND: %s\n", ( have_hwrnd == 1 ? "YES!" : "NO :-(" ) ); + } + if ( have_hwrnd == 1 ) { + int ret, retries = 10; + char ok; + while ( --retries > 0 ) { + __asm__ volatile ( "rdrand %0; setc %1" : "=r" ( ret ), "=qm" ( ok ) ); + if ( ok ) + return ret & 0x7fffffff; + } + } +#endif + /* Wait for next timer tick */ if ( ( efirc = bs->SetTimer ( tick, TimerRelative, EFI_ENTROPY_TRIGGER_TIME ) ) != 0 ) { diff --git a/src/interface/efi/efi_fbcon.c b/src/interface/efi/efi_fbcon.c index abc5a9390..1ea25df04 100644 --- a/src/interface/efi/efi_fbcon.c +++ b/src/interface/efi/efi_fbcon.c @@ -416,68 +416,70 @@ static int efifb_init ( struct console_configuration *config ) { EFI_STATUS efirc; int rc; - /* Locate graphics output protocol */ - if ( ( efirc = bs->LocateProtocol ( &efi_graphics_output_protocol_guid, - NULL, &interface ) ) != 0 ) { - rc = -EEFI ( efirc ); - DBGC ( &efifb, "EFIFB could not locate graphics output " - "protocol: %s\n", strerror ( rc ) ); - goto err_locate_gop; - } - efifb.gop = interface; + if ( ! config->lazy_update ) { + /* Locate graphics output protocol */ + if ( ( efirc = bs->LocateProtocol ( &efi_graphics_output_protocol_guid, + NULL, &interface ) ) != 0 ) { + rc = -EEFI ( efirc ); + DBGC ( &efifb, "EFIFB could not locate graphics output " + "protocol: %s\n", strerror ( rc ) ); + goto err_locate_gop; + } + efifb.gop = interface; - /* Locate HII font protocol */ - if ( ( efirc = bs->LocateProtocol ( &efi_hii_font_protocol_guid, - NULL, &interface ) ) != 0 ) { - rc = -EEFI ( efirc ); - DBGC ( &efifb, "EFIFB could not locate HII font protocol: %s\n", - strerror ( rc ) ); - goto err_locate_hiifont; - } - efifb.hiifont = interface; + /* Locate HII font protocol */ + if ( ( efirc = bs->LocateProtocol ( &efi_hii_font_protocol_guid, + NULL, &interface ) ) != 0 ) { + rc = -EEFI ( efirc ); + DBGC ( &efifb, "EFIFB could not locate HII font protocol: %s\n", + strerror ( rc ) ); + goto err_locate_hiifont; + } + efifb.hiifont = interface; - /* Locate glyphs */ - if ( ( rc = efifb_glyphs() ) != 0 ) - goto err_glyphs; + /* Locate glyphs */ + if ( ( rc = efifb_glyphs() ) != 0 ) + goto err_glyphs; - /* Save original mode */ - efifb.saved_mode = efifb.gop->Mode->Mode; + /* Save original mode */ + efifb.saved_mode = efifb.gop->Mode->Mode; - /* Select mode */ - if ( ( mode = efifb_select_mode ( config->width, config->height, - config->depth ) ) < 0 ) { - rc = mode; - goto err_select_mode; - } + /* Select mode */ + if ( ( mode = efifb_select_mode ( config->width, config->height, + config->depth ) ) < 0 ) { + rc = mode; + goto err_select_mode; + } - /* Set mode */ - if ( ( efirc = efifb.gop->SetMode ( efifb.gop, mode ) ) != 0 ) { - rc = -EEFI ( efirc ); - DBGC ( &efifb, "EFIFB could not set mode %d: %s\n", - mode, strerror ( rc ) ); - goto err_set_mode; - } - info = efifb.gop->Mode->Info; - - /* Populate colour map */ - bpp = efifb_colour_map ( info, &efifb.map ); - if ( bpp < 0 ) { - rc = bpp; - DBGC ( &efifb, "EFIFB could not build colour map for " - "mode %d: %s\n", mode, strerror ( rc ) ); - goto err_map; - } + /* Set mode */ + if ( ( efirc = efifb.gop->SetMode ( efifb.gop, mode ) ) != 0 ) { + rc = -EEFI ( efirc ); + DBGC ( &efifb, "EFIFB could not set mode %d: %s\n", + mode, strerror ( rc ) ); + goto err_set_mode; + } + info = efifb.gop->Mode->Info; - /* Populate pixel geometry */ - efifb.pixel.width = info->HorizontalResolution; - efifb.pixel.height = info->VerticalResolution; - efifb.pixel.len = ( ( bpp + 7 ) / 8 ); - efifb.pixel.stride = ( efifb.pixel.len * info->PixelsPerScanLine ); + /* Populate colour map */ + bpp = efifb_colour_map ( info, &efifb.map ); + if ( bpp < 0 ) { + rc = bpp; + DBGC ( &efifb, "EFIFB could not build colour map for " + "mode %d: %s\n", mode, strerror ( rc ) ); + goto err_map; + } - /* Populate frame buffer address */ - efifb.start = efifb.gop->Mode->FrameBufferBase; - DBGC ( &efifb, "EFIFB using mode %d (%dx%d %dbpp at %#08lx)\n", - mode, efifb.pixel.width, efifb.pixel.height, bpp, efifb.start ); + /* Populate pixel geometry */ + efifb.pixel.width = info->HorizontalResolution; + efifb.pixel.height = info->VerticalResolution; + efifb.pixel.len = ( ( bpp + 7 ) / 8 ); + efifb.pixel.stride = ( efifb.pixel.len * info->PixelsPerScanLine ); + + /* Populate frame buffer address */ + efifb.start = efifb.gop->Mode->FrameBufferBase; + DBGC ( &efifb, "EFIFB using mode %d (%dx%d %dbpp at %#08lx)\n", + mode, efifb.pixel.width, efifb.pixel.height, bpp, efifb.start ); +} /* Initialise frame buffer console */ if ( ( rc = fbcon_init ( &efifb.fbcon, phys_to_user ( efifb.start ), @@ -535,13 +537,32 @@ static void efifb_putchar ( int character ) { static int efifb_configure ( struct console_configuration *config ) { int rc; - /* Reset console, if applicable */ - if ( ! efifb_console.disabled ) { - efifb_fini(); - efi_console.disabled &= ~CONSOLE_DISABLED_OUTPUT; - ansicol_reset_magic(); + if ( config && config->lazy_update ) { + if ( efifb_console.disabled ) + return 0; + /* No width/height given, use current so we can update the border */ + if ( ( config->width == 0 ) || ( config->height == 0 ) ) { + if ( ( efifb.pixel.width == 0 ) || ( efifb.pixel.height == 0 ) ) { + return -EINVAL; + } + config->width = efifb.pixel.width; + config->height = efifb.pixel.height; + } else { + /* Otherwise make sure the new dimensions match the old ones */ + if ( ( efifb.pixel.width != config->width ) || + ( efifb.pixel.height != config->height ) ) { + return -EINVAL; + } + } + } else { + /* Reset console, if applicable */ + if ( ! efifb_console.disabled ) { + efifb_fini(); + efi_console.disabled &= ~CONSOLE_DISABLED_OUTPUT; + ansicol_reset_magic(); + } + efifb_console.disabled = CONSOLE_DISABLED; } - efifb_console.disabled = CONSOLE_DISABLED; /* Do nothing more unless we have a usable configuration */ if ( ( config == NULL ) || @@ -553,13 +574,15 @@ static int efifb_configure ( struct console_configuration *config ) { if ( ( rc = efifb_init ( config ) ) != 0 ) return rc; - /* Mark console as enabled */ - efifb_console.disabled = 0; - efi_console.disabled |= CONSOLE_DISABLED_OUTPUT; + if ( ! config->lazy_update ) { + /* Mark console as enabled */ + efifb_console.disabled = 0; + efi_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; } |
