mirror of https://github.com/ipxe/ipxe.git
[efi] Prescroll the display after a failed wrapped ExitBootServices() call
On some systems (observed with an HP Elitebook 840 G10), writing console output that happens to cause the display to scroll will modify the system memory map. This causes builds with DEBUG=efi_wrap to typically fail to boot, since the debug output from the wrapped ExitBootServices() call itself is sufficient to change the memory map and therefore cause ExitBootServices() to fail due to an invalid memory map key. Work around these UEFI firmware bugs by prescrolling the display after a failed ExitBootServices() attempt, in order to minimise the chance that further scrolling will happen during the subsequent attempt. Signed-off-by: Michael Brown <mcb30@ipxe.org>pull/1165/merge
parent
8ea8411f0d
commit
6e4196baff
|
@ -40,6 +40,9 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
|||
/** Colour for debug messages */
|
||||
#define colour &efi_systab
|
||||
|
||||
/** Number of lines to prescroll when needed */
|
||||
#define EFI_WRAP_PRESCROLL 16
|
||||
|
||||
/**
|
||||
* Convert EFI status code to text
|
||||
*
|
||||
|
@ -195,6 +198,38 @@ static const char * efi_timer_delay ( EFI_TIMER_DELAY type ) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pre-scroll display to create space for output lines
|
||||
*
|
||||
* @v lines Number of lines required
|
||||
* @ret efirc EFI status code
|
||||
*/
|
||||
static int efi_prescroll ( unsigned int lines ) {
|
||||
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *conout = efi_systab->ConOut;
|
||||
UINTN columns;
|
||||
UINTN rows;
|
||||
UINTN space;
|
||||
EFI_STATUS efirc;
|
||||
|
||||
/* Get number of rows and columns */
|
||||
if ( ( efirc = conout->QueryMode ( conout, conout->Mode->Mode,
|
||||
&columns, &rows ) ) != 0 )
|
||||
return efirc;
|
||||
|
||||
/* Calculate available space */
|
||||
space = ( rows - conout->Mode->CursorRow - 1 );
|
||||
|
||||
/* Scroll to create space */
|
||||
while ( space++ < lines )
|
||||
conout->OutputString ( conout, L"\n" );
|
||||
|
||||
/* Move cursor to start of space */
|
||||
conout->SetCursorPosition ( conout, 0,
|
||||
( conout->Mode->CursorRow - lines ) );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump information about a loaded image
|
||||
*
|
||||
|
@ -783,6 +818,15 @@ efi_exit_boot_services_wrapper ( EFI_HANDLE image_handle, UINTN map_key ) {
|
|||
if ( efirc != 0 ) {
|
||||
DBGC ( colour, "ExitBootServices ( ... ) = %s -> %p\n",
|
||||
efi_status ( efirc ), retaddr );
|
||||
/* On some systems, scrolling the output will cause
|
||||
* the system memory map to change (and so cause
|
||||
* ExitBootServices() to fail).
|
||||
*
|
||||
* After the first failed attempt, prescroll the
|
||||
* screen to maximise the chance of the subsequent
|
||||
* attempt succeeding.
|
||||
*/
|
||||
efi_prescroll ( EFI_WRAP_PRESCROLL );
|
||||
}
|
||||
return efirc;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue