From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=134.134.136.31; helo=mga06.intel.com; envelope-from=ruiyu.ni@intel.com; receiver=edk2-devel@lists.01.org Received: from mga06.intel.com (mga06.intel.com [134.134.136.31]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 8F1C321A02937 for ; Thu, 28 Jun 2018 00:40:01 -0700 (PDT) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga005.jf.intel.com ([10.7.209.41]) by orsmga104.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 28 Jun 2018 00:39:59 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.51,282,1526367600"; d="scan'208";a="236257645" Received: from ray-dev.ccr.corp.intel.com ([10.239.9.4]) by orsmga005.jf.intel.com with ESMTP; 28 Jun 2018 00:39:59 -0700 From: Ruiyu Ni To: edk2-devel@lists.01.org Cc: Sean Brogan , Michael Turner , Laszlo Ersek Date: Thu, 28 Jun 2018 15:40:20 +0800 Message-Id: <20180628074020.53444-1-ruiyu.ni@intel.com> X-Mailer: git-send-email 2.16.1.windows.1 Subject: [PATCH] MdeModulePkg/UefiBootManagerLib: handle ultimate boot failure X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.26 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 28 Jun 2018 07:40:01 -0000 When no boot option could be launched including platform recovery options and options pointing to applications built into firmware volumes, a platform callback registered through EfiBootManagerRegisterUnableBootHandler() is called. If there is no platform callback registered, default behavior is to print an error message to the screen and wait for user input. Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Ruiyu Ni Cc: Sean Brogan Cc: Michael Turner Cc: Laszlo Ersek --- MdeModulePkg/Include/Library/UefiBootManagerLib.h | 48 +++++++++++++++++++++++ MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c | 41 +++++++++++++++++++ MdeModulePkg/Universal/BdsDxe/BdsEntry.c | 44 +++++++++++---------- 3 files changed, 113 insertions(+), 20 deletions(-) diff --git a/MdeModulePkg/Include/Library/UefiBootManagerLib.h b/MdeModulePkg/Include/Library/UefiBootManagerLib.h index bfc0cb86f8..0035c41082 100644 --- a/MdeModulePkg/Include/Library/UefiBootManagerLib.h +++ b/MdeModulePkg/Include/Library/UefiBootManagerLib.h @@ -800,4 +800,52 @@ EFIAPI EfiBootManagerDispatchDeferredImages ( VOID ); + +/** + The function is called when no boot option could be launched, + including platform recovery options and options pointing to applications + built into firmware volumes. + + The platform may register this function to inform the user about the above fact. + If this function returns, BDS core attempts to enter an infinite loop of pulling + up the Boot Manager Menu (if the platform includes the Boot Manager Menu). + If the Boot Manager Menu is unavailable, BDS will hang. +**/ +typedef +VOID +(EFIAPI *EFI_BOOT_MANAGER_UNABLE_BOOT) ( + VOID + ); + +/** + Register the callback function when no boot option could be launched, + including platform recovery options and options pointing to applications + built into firmware volumes. + + @param Handler The callback function. +**/ +VOID +EFIAPI +EfiBootManagerRegisterUnableBootHandler ( + EFI_BOOT_MANAGER_UNABLE_BOOT Handler + ); + +/** + The function is called when no boot option could be launched, + including platform recovery options and options pointing to applications + built into firmware volumes. + + If this function returns, BDS core attempts to enter an infinite loop of pulling + up the Boot Manager Menu (if the platform includes the Boot Manager Menu). + If the Boot Manager Menu is unavailable, BDS will hang. + + @retval EFI_SUCCESS The unable-boot callback is called successfully. + @retval EFI_UNSUPPORTED There is no unable-boot callback registered. +**/ +EFI_STATUS +EFIAPI +EfiBootManagerUnableBoot ( + VOID + ); + #endif diff --git a/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c b/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c index 6a23477eb8..122068267d 100644 --- a/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c +++ b/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c @@ -19,6 +19,7 @@ EFI_RAM_DISK_PROTOCOL *mRamDisk = NULL; EFI_BOOT_MANAGER_REFRESH_LEGACY_BOOT_OPTION mBmRefreshLegacyBootOption = NULL; EFI_BOOT_MANAGER_LEGACY_BOOT mBmLegacyBoot = NULL; +EFI_BOOT_MANAGER_UNABLE_BOOT mBmUnableBoot = NULL; /// /// This GUID is used for an EFI Variable that stores the front device pathes @@ -2461,3 +2462,43 @@ EfiBootManagerGetBootManagerMenu ( } } +/** + Register the callback function when no boot option could be launched, + including platform recovery options and options pointing to applications + built into firmware volumes. + + @param Handler The callback function. +**/ +VOID +EFIAPI +EfiBootManagerRegisterUnableBootHandler ( + EFI_BOOT_MANAGER_UNABLE_BOOT Handler + ) +{ + mBmUnableBoot = Handler; +} + +/** + The function is called when no boot option could be launched, + including platform recovery options and options pointing to applications + built into firmware volumes. + + If this function returns, BDS core attempts to enter an infinite loop of pulling + up the Boot Manager Menu (if the platform includes the Boot Manager Menu). + If the Boot Manager Menu is unavailable, BDS will hang. + + @retval EFI_SUCCESS The unable-boot callback is called successfully. + @retval EFI_UNSUPPORTED There is no unable-boot callback registered. +**/ +EFI_STATUS +EFIAPI +EfiBootManagerUnableBoot ( + VOID + ) +{ + if (mBmUnableBoot != NULL) { + mBmUnableBoot (); + return EFI_SUCCESS; + } + return EFI_UNSUPPORTED; +} diff --git a/MdeModulePkg/Universal/BdsDxe/BdsEntry.c b/MdeModulePkg/Universal/BdsDxe/BdsEntry.c index 49e403e181..0cb9b04dfb 100644 --- a/MdeModulePkg/Universal/BdsDxe/BdsEntry.c +++ b/MdeModulePkg/Universal/BdsDxe/BdsEntry.c @@ -649,32 +649,36 @@ BdsBootManagerMenuLoop ( IN EFI_BOOT_MANAGER_LOAD_OPTION *BootManagerMenu ) { + EFI_STATUS Status; 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); - + Status = EfiBootManagerUnableBoot (); + if (EFI_ERROR (Status)) { + // + // If platform doesn't register any unable-boot callback, this is + // a last resort -- the end-user will likely not see any DEBUG messages + // logged in this situation. // - // Drain any queued keys. + // 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. // - while (!EFI_ERROR (gST->ConIn->ReadKeyStroke (gST->ConIn, &Key))) { + 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); + // - // just throw away Key + // Drain any queued keys. // + while (!EFI_ERROR (gST->ConIn->ReadKeyStroke (gST->ConIn, &Key))) { + // + // just throw away Key + // + } } } -- 2.16.1.windows.1