diff options
author | Nick Bofferding <bofferdn@us.ibm.com> | 2017-07-21 11:15:42 -0500 |
---|---|---|
committer | William G. Hoffa <wghoffa@us.ibm.com> | 2017-07-28 10:43:42 -0400 |
commit | f54d606af645343351d086b1de237f021f38cb21 (patch) | |
tree | 5f0a86acb216888dc0f15e71c6032c0d795b444e | |
parent | 481baf1c81c945ce3d354097a6452cb8ecba38d6 (diff) | |
download | talos-hostboot-f54d606af645343351d086b1de237f021f38cb21.tar.gz talos-hostboot-f54d606af645343351d086b1de237f021f38cb21.zip |
Secure Boot: Shutdown after key transition
- Fence off istep path after istep dispatcher stops
- Automatically power off after a key transition has completed
- Added IPMI API to power off system
Change-Id: I74eaec08e86d0cbc46db6aa1674845c53bcf14d4
RTC: 174017
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/43436
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com>
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Reviewed-by: Michael Baiocchi <mbaiocch@us.ibm.com>
Reviewed-by: Marshall J. Wilks <mjwilks@us.ibm.com>
Reviewed-by: Stephen M. Cprek <smcprek@us.ibm.com>
Reviewed-by: William G. Hoffa <wghoffa@us.ibm.com>
-rw-r--r-- | src/include/usr/initservice/initsvcreasoncodes.H | 1 | ||||
-rw-r--r-- | src/include/usr/initservice/istepdispatcherif.H | 14 | ||||
-rw-r--r-- | src/include/usr/ipmi/ipmiif.H | 34 | ||||
-rw-r--r-- | src/usr/initservice/istepdispatcher/istepdispatcher.C | 65 | ||||
-rw-r--r-- | src/usr/initservice/istepdispatcher/istepdispatcher.H | 7 | ||||
-rw-r--r-- | src/usr/ipmi/ipmirp.C | 34 | ||||
-rw-r--r-- | src/usr/ipmi/ipmirp.H | 16 | ||||
-rw-r--r-- | src/usr/sbe/sbe_update.C | 69 |
8 files changed, 187 insertions, 53 deletions
diff --git a/src/include/usr/initservice/initsvcreasoncodes.H b/src/include/usr/initservice/initsvcreasoncodes.H index 31910bcef..29f73e253 100644 --- a/src/include/usr/initservice/initsvcreasoncodes.H +++ b/src/include/usr/initservice/initsvcreasoncodes.H @@ -77,6 +77,7 @@ enum InitServiceReasonCode //termination_rc SHUTDOWN_NOT_RECONFIG_LOOP = INITSVC_COMP_ID | 0x10, ISTEP_SKIP_ATTEMPTED = INITSVC_COMP_ID | 0x11, + ISTEP_PROCESSING_DISABLED = INITSVC_COMP_ID | 0x12, }; enum InitServiceUserDetailDataSubSection diff --git a/src/include/usr/initservice/istepdispatcherif.H b/src/include/usr/initservice/istepdispatcherif.H index 752f9ffff..1694c7942 100644 --- a/src/include/usr/initservice/istepdispatcherif.H +++ b/src/include/usr/initservice/istepdispatcherif.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2012,2016 */ +/* Contributors Listed Below - COPYRIGHT 2012,2017 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -78,12 +78,16 @@ void stopIpl( void ); #ifdef CONFIG_BMC_IPMI /** - * @brief This function is to be used by external code to - * initate a system reboot via IPMI commands - * - * @return Nothing + * @brief This function is to be used by external code to + * initiate a system reboot via IPMI commands */ void requestReboot( void ); + +/** + * @brief This function is to be used by external code to + * initiate a system power off via IPMI commands + */ +void requestPowerOff( void ); #endif /** diff --git a/src/include/usr/ipmi/ipmiif.H b/src/include/usr/ipmi/ipmiif.H index 09f0c4830..4dd5e7cbb 100644 --- a/src/include/usr/ipmi/ipmiif.H +++ b/src/include/usr/ipmi/ipmiif.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2012,2016 */ +/* Contributors Listed Below - COPYRIGHT 2012,2017 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -54,13 +54,30 @@ namespace IPMI MSG_STATE_GRACEFUL_SHUTDOWN, - // initate a reboot request - MSG_STATE_INITATE_POWER_CYCLE, + // initiate a reboot request + MSG_STATE_INITIATE_POWER_CYCLE, // Used to check range. Leave as last. - MSG_LAST_TYPE = MSG_STATE_INITATE_POWER_CYCLE, + MSG_LAST_TYPE = MSG_STATE_INITIATE_POWER_CYCLE, }; + /** + * @brief Returns whether IPMI message type is related to + * system shutdown/reboot or not + * + * @param[in] i_msgType IPMI message type in question + * + * @return bool True or false value indicating whether requested IPMI + * message type is related to system shutdown/reboot or not + */ + inline bool validShutdownRebootMsgType(const msg_type i_msgType) + { + return ( (i_msgType == MSG_STATE_SHUTDOWN) + || (i_msgType == MSG_STATE_SHUTDOWN_SEL) + || (i_msgType == MSG_STATE_GRACEFUL_SHUTDOWN) + || (i_msgType == MSG_STATE_INITIATE_POWER_CYCLE)); + } + // chassis power off request types enum power_request_type { @@ -349,12 +366,17 @@ namespace IPMI size_t max_buffer(void); /** - * Tells ipmirp to start a graceful reboot sequence - * + * @brief Initiate a graceful reboot sequence via the IPMI resource + * provider */ void initiateReboot(); /** + * @brief Initiate a power off sequence via the IPMI resource provider + */ + void initiatePowerOff(); + + /** * Structure to return BMC/IPMI information in */ struct BmcInfo_t diff --git a/src/usr/initservice/istepdispatcher/istepdispatcher.C b/src/usr/initservice/istepdispatcher/istepdispatcher.C index 2444b98ad..5edf4f835 100644 --- a/src/usr/initservice/istepdispatcher/istepdispatcher.C +++ b/src/usr/initservice/istepdispatcher/istepdispatcher.C @@ -655,6 +655,9 @@ errlHndl_t IStepDispatcher::executeAllISteps() // possible ERRORLOG::ErrlManager::callFlushErrorLogs(); + // Quiesce new isteps, including external requests + (void)setStopIpl(); + // Stop the IPL stop(); } @@ -1505,11 +1508,20 @@ void IStepDispatcher::handleShutdownMsg(msg_t * & io_pMsg) #ifdef CONFIG_BMC_IPMI void IStepDispatcher::requestReboot() { - // always stop dispatching isteps before calling for the reboot - setStopIpl(); + // Always stop dispatching isteps before calling for the reboot + (void)setStopIpl(); + + // Send a reboot message to the BMC + (void)IPMI::initiateReboot(); +} + +void IStepDispatcher::requestPowerOff() +{ + // Always stop dispatching isteps before calling for the power off + (void)setStopIpl(); - // send a reboot message to the BMC - IPMI::initiateReboot(); + // Send a power off message to the BMC + (void)IPMI::initiatePowerOff(); } #endif // ---------------------------------------------------------------------------- @@ -1744,21 +1756,42 @@ void IStepDispatcher::handleIStepRequestMsg(msg_t * & io_pMsg) l_acceptMessages = iv_acceptIstepMessages; mutex_unlock(&iv_mutex); - if (l_acceptMessages) + // If istep dispatching has ceased, prevent new isteps from executing + if(iv_stopIpl == true) + { + /*@ + * @errortype + * @reasoncode ISTEP_PROCESSING_DISABLED + * @severity ERRORLOG::ERRL_SEV_INFORMATIONAL + * @moduleid ISTEP_INITSVC_MOD_ID + * @userdata1 Istep Requested + * @userdata2 Substep Requested + * @devdesc Istep processing has terminated due to normal shutdown + * activity, secure boot key transition, or terminating error + * @custdesc Node is no longer accepting istep requests + */ + err = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_INFORMATIONAL, + ISTEP_INITSVC_MOD_ID, + ISTEP_PROCESSING_DISABLED, + istep, + substep); + } + else if (l_acceptMessages) { err = doIstep (istep, substep, l_doReconfig); } else { /*@ - * @errortype - * @reasoncode ISTEP_NON_MASTER_NODE_MSG - * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE - * @moduleid ISTEP_INITSVC_MOD_ID - * @userdata1 Istep Requested - * @userdata2 Substep Requested - * @devdesc Istep messaged received by non-master node. - */ + * @errortype + * @reasoncode ISTEP_NON_MASTER_NODE_MSG + * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE + * @moduleid ISTEP_INITSVC_MOD_ID + * @userdata1 Istep Requested + * @userdata2 Substep Requested + * @devdesc Istep messaged received by non-master node. + */ err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, ISTEP_INITSVC_MOD_ID, @@ -2236,9 +2269,15 @@ void requestReboot() { IStepDispatcher::getTheInstance().requestReboot(); } + +void requestPowerOff() +{ + IStepDispatcher::getTheInstance().requestPowerOff(); +} #endif void stopIpl() { + // Disable the istep dispatcher return IStepDispatcher::getTheInstance().setStopIpl(); } diff --git a/src/usr/initservice/istepdispatcher/istepdispatcher.H b/src/usr/initservice/istepdispatcher/istepdispatcher.H index cd3c26dcb..59e0fd45b 100644 --- a/src/usr/initservice/istepdispatcher/istepdispatcher.H +++ b/src/usr/initservice/istepdispatcher/istepdispatcher.H @@ -216,9 +216,14 @@ public: void stop(); #ifdef CONFIG_BMC_IPMI /** - * @brief This function will trigger a reboot via ipmi commands + * @brief Trigger a reboot via IPMI commands */ void requestReboot(); + + /** + * @brief Trigger a power off via IPMI commands + */ + void requestPowerOff(); #endif /** diff --git a/src/usr/ipmi/ipmirp.C b/src/usr/ipmi/ipmirp.C index 4c5db3f19..6b1138783 100644 --- a/src/usr/ipmi/ipmirp.C +++ b/src/usr/ipmi/ipmirp.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2012,2016 */ +/* Contributors Listed Below - COPYRIGHT 2012,2017 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -696,8 +696,8 @@ void IpmiRP::execute(void) } break; - // begin a graceful reboot initated by us - case IPMI::MSG_STATE_INITATE_POWER_CYCLE: + // begin a graceful reboot initiated by us + case IPMI::MSG_STATE_INITIATE_POWER_CYCLE: { msg_free(msg); @@ -1078,15 +1078,27 @@ namespace IPMI return err; } - /// - /// @brief kick off a reboot - /// + void initiateShutdownOrReboot(const IPMI::msg_type i_msgType) + { + const auto valid = IPMI::validShutdownRebootMsgType(i_msgType); + assert(valid,"BUG! IPMI message type of 0x%08X is not a valid shutdown " + "or reboot type",i_msgType); + static auto mq = Singleton<IpmiRP>::instance().msgQueue(); + auto pMsg = msg_allocate(); + assert(pMsg != nullptr,"BUG! msg_allocate returned nullptr."); + pMsg->type = i_msgType; + auto rc = msg_send(mq,pMsg); + assert(!rc,"BUG! msg_send failed with rc of %d",rc); + } + void initiateReboot() { - static msg_q_t mq = Singleton<IpmiRP>::instance().msgQueue(); - msg_t * msg = msg_allocate(); - msg->type = IPMI::MSG_STATE_INITATE_POWER_CYCLE; - msg_send(mq, msg); + (void)initiateShutdownOrReboot(MSG_STATE_INITIATE_POWER_CYCLE); + } + + void initiatePowerOff() + { + (void)initiateShutdownOrReboot(MSG_STATE_GRACEFUL_SHUTDOWN); } /// @@ -1163,4 +1175,4 @@ namespace IPMI return l_info; } -}; +}; // End namespace IPMI diff --git a/src/usr/ipmi/ipmirp.H b/src/usr/ipmi/ipmirp.H index 9e8832555..0bbbaafb2 100644 --- a/src/usr/ipmi/ipmirp.H +++ b/src/usr/ipmi/ipmirp.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2012,2015 */ +/* Contributors Listed Below - COPYRIGHT 2012,2017 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -267,4 +267,18 @@ class IpmiRP IpmiRP(const IpmiRP&); }; +namespace IPMI +{ + /** + * @brief Initiate generic IPMI shutdown/reboot request via the IPMI + * resource provider + * + * @param[in] i_msgType IPMI message type indicating the shutdown or reboot + * to request. Asserts if not a valid shutdown or reboot message type as + * determined by IPMI::validShutdownRebootMsgType(). + */ + void initiateShutdownOrReboot(IPMI::msg_type i_msgType); + +} // End IPMI namespace + #endif diff --git a/src/usr/sbe/sbe_update.C b/src/usr/sbe/sbe_update.C index 7fe922427..ee116b14a 100644 --- a/src/usr/sbe/sbe_update.C +++ b/src/usr/sbe/sbe_update.C @@ -54,6 +54,8 @@ #include <sbeio/sbeioif.H> #include <sbe/sbereasoncodes.H> #include <sbe/sbe_update.H> +#include <initservice/initsvcreasoncodes.H> + #ifdef CONFIG_BMC_IPMI #include <ipmi/ipmisensor.H> #include <ipmi/ipmiwatchdog.H> @@ -481,8 +483,10 @@ namespace SBE /**************************************************************/ /* Perform System Operation */ /**************************************************************/ - // Restart IPL if SBE Update requires it - if ( l_restartNeeded == true ) + + // Restart IPL if SBE Update requires it or key transition occurred + if ( (l_restartNeeded == true) + || (g_do_hw_keys_hash_transition)) { TRACFCOMP( g_trac_sbe, INFO_MRK"updateProcessorSbeSeeproms(): Restart " @@ -5037,25 +5041,58 @@ errlHndl_t sbeDoReboot( void ) #endif #ifdef CONFIG_CONSOLE - CONSOLE::displayf(SBE_COMP_NAME, "System Rebooting To " - "Perform SBE Update\n"); - CONSOLE::flush(); + if(g_do_hw_keys_hash_transition) + { + CONSOLE::displayf(SBE_COMP_NAME, "Performing Secure Boot key transition\n"); + CONSOLE::displayf(SBE_COMP_NAME, "System will power off after completion\n"); + CONSOLE::flush(); + } + else + { + CONSOLE::displayf(SBE_COMP_NAME, "System Rebooting To " + "Perform SBE Update\n"); + CONSOLE::flush(); + } #endif #ifdef CONFIG_BMC_IPMI - // initate a graceful power cycle - TRACFCOMP( g_trac_sbe,"sbeDoReboot: " - "requesting chassis power cycle"); - INITSERVICE::requestReboot(); + if(g_do_hw_keys_hash_transition) + { + // Initiate a graceful power off + TRACFCOMP(g_trac_sbe, + INFO_MRK"sbeDoReboot(): Performing Secure Boot key transition. " + "Requesting power off"); + INITSERVICE::requestPowerOff(); + } + else + { + // Initiate a graceful power cycle + TRACFCOMP( g_trac_sbe,"sbeDoReboot: " + "requesting power cycle"); + INITSERVICE::requestReboot(); + } #else //non-IPMI - TRACFCOMP( g_trac_sbe, - INFO_MRK"sbeDoReboot(): Calling " - "INITSERVICE::doShutdown() with " - "SBE_UPDATE_REQUEST_REIPL = 0x%X", - SBE_UPDATE_REQUEST_REIPL ); - // shutdown/TI hostboot - INITSERVICE::doShutdown(SBE_UPDATE_REQUEST_REIPL); + if(g_do_hw_keys_hash_transition) + { + TRACFCOMP(g_trac_sbe, + INFO_MRK"sbeDoReboot(): Performing Secure Boot key transition. " + "Calling INITSERVICE::doShutdown() with " + "SHUTDOWN_NOT_RECONFIG_LOOP = 0x%08X", + INITSERVICE::SHUTDOWN_NOT_RECONFIG_LOOP ); + INITSERVICE::doShutdown(INITSERVICE:: + SHUTDOWN_NOT_RECONFIG_LOOP); + } + else + { + TRACFCOMP( g_trac_sbe, + INFO_MRK"sbeDoReboot(): Calling " + "INITSERVICE::doShutdown() with " + "SBE_UPDATE_REQUEST_REIPL = 0x%08X", + SBE_UPDATE_REQUEST_REIPL ); + // shutdown/TI hostboot + INITSERVICE::doShutdown(SBE_UPDATE_REQUEST_REIPL); + } #endif }while(0); |