MdeModulePkg/BdsDxe: fall back to a Boot Manager Menu loop before hanging

Under the following scenario:

- no UEFI bootable application available anywhere in the system,
- ... not even for the default platform recovery option,
- no shell is built into the firmware image,
- but UiApp is available in the firmware image,

we should preferably not just hang in BdsEntry() with:

   DEBUG ((EFI_D_ERROR, "[Bds] Unable to boot!\n"));
   CpuDeadLoop ();

while the user sits at the TianoCore logo page, wondering what's going on.
Print an informative message to the console, wait for a keypress, and then
return to the Boot Manager Menu forever.

Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ruiyu Ni <ruiyu.ni@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Ref: https://bugzilla.redhat.com/show_bug.cgi?id=1515418
Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=513
Suggested-by: Ruiyu Ni <ruiyu.ni@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Ruiyu Ni <ruiyu.ni@intel.com>
This commit is contained in:
Laszlo Ersek 2017-11-22 17:48:38 +01:00
parent c3cb333e09
commit d1de487dd2
1 changed files with 56 additions and 4 deletions

View File

@ -685,6 +685,55 @@ BdsAllocateMemoryForPerformanceData (
}
}
/**
Enter an infinite loop of calling the Boot Manager Menu.
This is a last resort alternative to BdsEntry() giving up for good. This
function never returns.
@param[in] BootManagerMenu The EFI_BOOT_MANAGER_LOAD_OPTION located and/or
created by the EfiBootManagerGetBootManagerMenu()
call in BdsEntry().
**/
VOID
BdsBootManagerMenuLoop (
IN EFI_BOOT_MANAGER_LOAD_OPTION *BootManagerMenu
)
{
EFI_INPUT_KEY Key;
//
// Normally BdsDxe does not print anything to the system console, but this is
// a last resort -- the end-user will likely not see any DEBUG messages
// logged in this situation.
//
// AsciiPrint() will NULL-check gST->ConOut internally. We check gST->ConIn
// here to see if it makes sense to request and wait for a keypress.
//
if (gST->ConIn != NULL) {
AsciiPrint (
"%a: No bootable option or device was found.\n"
"%a: Press any key to enter the Boot Manager Menu.\n",
gEfiCallerBaseName,
gEfiCallerBaseName
);
BdsWaitForSingleEvent (gST->ConIn->WaitForKey, 0);
//
// Drain any queued keys.
//
while (!EFI_ERROR (gST->ConIn->ReadKeyStroke (gST->ConIn, &Key))) {
//
// just throw away Key
//
}
}
for (;;) {
EfiBootManagerBoot (BootManagerMenu);
}
}
/**
Service routine for BdsInstance->Entry(). Devices are connected, the
@ -1088,16 +1137,19 @@ BdsEntry (
} while (BootSuccess);
}
if (BootManagerMenuStatus != EFI_NOT_FOUND) {
EfiBootManagerFreeLoadOption (&BootManagerMenu);
}
if (!BootSuccess) {
LoadOptions = EfiBootManagerGetLoadOptions (&LoadOptionCount, LoadOptionTypePlatformRecovery);
ProcessLoadOptions (LoadOptions, LoadOptionCount);
EfiBootManagerFreeLoadOptions (LoadOptions, LoadOptionCount);
}
//
// If BootManagerMenu is available, fall back to it indefinitely.
//
if (BootManagerMenuStatus != EFI_NOT_FOUND) {
BdsBootManagerMenuLoop (&BootManagerMenu);
}
DEBUG ((EFI_D_ERROR, "[Bds] Unable to boot!\n"));
CpuDeadLoop ();
}