diff --git a/src/include/usr/initservice/istepdispatcherif.H b/src/include/usr/initservice/istepdispatcherif.H index c4dee288900..e7b8bf21fd0 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,2018 */ +/* Contributors Listed Below - COPYRIGHT 2012,2020 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -107,6 +107,12 @@ void requestReboot( void ); * initiate a system power off via IPMI commands */ void requestPowerOff( void ); + +/** + * @brief This function is to be used by external code to + * initiate a soft system power off via IPMI commands + */ +void requestSoftPowerOff( void ); #endif /** diff --git a/src/include/usr/ipmi/ipmiif.H b/src/include/usr/ipmi/ipmiif.H index 68adfa392c0..a8100e97489 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,2019 */ +/* Contributors Listed Below - COPYRIGHT 2012,2020 */ /* [+] Google Inc. */ /* [+] International Business Machines Corp. */ /* [+] Maxim Polyakov */ @@ -57,8 +57,11 @@ namespace IPMI // initiate a reboot request MSG_STATE_INITIATE_POWER_CYCLE, + // initiate a soft power off + MSG_STATE_INITIATE_SOFT_POWER_OFF, + // Used to check range. Leave as last. - MSG_LAST_TYPE = MSG_STATE_INITIATE_POWER_CYCLE, + MSG_LAST_TYPE = MSG_STATE_INITIATE_SOFT_POWER_OFF, }; /** @@ -74,16 +77,20 @@ namespace IPMI { return ( (i_msgType == MSG_STATE_SHUTDOWN) || (i_msgType == MSG_STATE_GRACEFUL_SHUTDOWN) + || (i_msgType == MSG_STATE_INITIATE_SOFT_POWER_OFF) || (i_msgType == MSG_STATE_INITIATE_POWER_CYCLE)); } // chassis power off request types + // See Section 28.3, Table 28 "Chassis Control Command" in IPMI spec v2.0 enum power_request_type { CHASSIS_POWER_OFF = 0x00, - CHASSIS_POWER_SOFT_RESET = 0x01, + CHASSIS_POWER_ON = 0x01, CHASSIS_POWER_CYCLE = 0x02, CHASSIS_POWER_RESET = 0x03, + CHASSIS_POWER_PULSE_DIAGNOSTIC_INTR = 0x04, + CHASSIS_POWER_SOFT_OFF_VIA_OVER_TEMP = 0x05, // Use for Soft Power Off }; // Used in the factory for creating the proper subclass. @@ -418,6 +425,11 @@ namespace IPMI */ void initiatePowerOff(); + /** + * @brief Initiate a soft power off sequence via the IPMI resource provider + */ + void initiateSoftPowerOff(); + /** * Structure to return BMC/IPMI information in */ diff --git a/src/include/usr/ipmi/ipmisensor.H b/src/include/usr/ipmi/ipmisensor.H index 4da69dc0c1d..aa76518d1d2 100644 --- a/src/include/usr/ipmi/ipmisensor.H +++ b/src/include/usr/ipmi/ipmisensor.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2014,2018 */ +/* Contributors Listed Below - COPYRIGHT 2014,2020 */ /* [+] Google Inc. */ /* [+] International Business Machines Corp. */ /* */ @@ -1058,6 +1058,66 @@ namespace SENSOR }; + /** + * @class KeyClearRequestSensor + * + * @brief Specialized class for the key clear request sensor + * + * @par Detailed Description: + * Provides the functionality needed to set the key clear request + * sensor. The key clear request sensor is a special sensor + * maintained by the BMC. + * + * Usage: + * uint8_t key_clear_request_value = 0x0100; + * KeyClearRequestSensor l_sensor; + * l_sensor.setKeyClearRequestValue( key_clear_request_value ); + * + */ + class KeyClearRequestSensor : public SensorBase + { + + public: + + /** + * @brief Constructor for the KeyClearRequestSensor + * + * The key clear request sensor is used to notify various firmware + * levels (like hostboot, OPAL, PHYP, etc) if there is a request + * to clear certain security keys or certificates. + * + * The system target holds the IPMI sensor number for this sensor. + */ + KeyClearRequestSensor(); + + /** + * @brief Destructor for the KeyClearRequestSensor + * + */ + ~KeyClearRequestSensor(); + + /** + * @brief Set the value for the key clear request sensor on the BMC. + * + * @param[in] i_value - new key clear sensor value. + * + * @return Errorlog handle + * + */ + errlHndl_t setKeyClearRequest( uint8_t i_value ); + + /** + * @brief Get the value of the key clear request sensor from the BMC + * + * @param[o] o_value - new key clear request value. + * + * @return Errorlog handle + * + */ + errlHndl_t getKeyClearRequest( uint8_t & o_value ); + + }; + /* * @brief Return the fault sensor number for a target * Will return either the status sensor or Fault sensor number for a diff --git a/src/include/usr/secureboot/key_clear_if.H b/src/include/usr/secureboot/key_clear_if.H index 9a09755f975..26f6d21282c 100644 --- a/src/include/usr/secureboot/key_clear_if.H +++ b/src/include/usr/secureboot/key_clear_if.H @@ -45,17 +45,22 @@ namespace SECUREBOOT * @brief Returns Key Clear Request information and if a Physical Presence * check is requested * - * @param[out] o_requestPhysPresence - If true, then physical presence - * assertion is requested; otherwise - * false + * @param[out] o_requestPhysPresence - If true, then physical presence + * assertion is requested; otherwise + * false + * + * @param[out] o_keyClearRequests - Struct containing the specifics of + * the key clear requests + * + * @note Any error logs generated will be handled internally + * + * @note The associated ATTR_KEY_CLEAR_REQUEST will also be updated by + * this function * - * @param[out] o_keyClearRequests - Struct containing the specifics of - * the key clear requests * @return errlHndl_t nullptr on success; non-nullptr on error. */ - errlHndl_t getKeyClearRequest( - bool & o_requestPhysPresence, - TARGETING::KEY_CLEAR_REQUEST & o_keyClearRequests); + void getKeyClearRequest(bool & o_requestPhysPresence, + TARGETING::KEY_CLEAR_REQUEST & o_keyClearRequests); #ifdef CONFIG_BMC_IPMI /* diff --git a/src/include/usr/secureboot/secure_reasoncodes.H b/src/include/usr/secureboot/secure_reasoncodes.H index 0f89ffc8e28..28a624d5544 100644 --- a/src/include/usr/secureboot/secure_reasoncodes.H +++ b/src/include/usr/secureboot/secure_reasoncodes.H @@ -75,7 +75,7 @@ namespace SECUREBOOT // Requests MOD_DETECT_PHYS_PRES = 0x40, MOD_HANDLE_PHYS_PRES_WINDOW = 0x41, - + MOD_CLEAR_KEY_CLEAR_SENSOR = 0x42, }; enum SECUREReasonCode @@ -141,7 +141,7 @@ namespace SECUREBOOT RC_PHYS_PRES_WINDOW_NOT_OPENED = SECURE_COMP_ID | 0x43, RC_PHYS_PRES_ASSERTED = SECURE_COMP_ID | 0x44, RC_PHYS_PRES_REIPL = SECURE_COMP_ID | 0x45, - + RC_CLEARING_KEY_CLEAR_SENSOR_FAILED = SECURE_COMP_ID | 0x46, // Reason codes 0xA0 - 0xEF reserved for trustedboot_reasoncodes.H }; diff --git a/src/usr/initservice/istepdispatcher/istepdispatcher.C b/src/usr/initservice/istepdispatcher/istepdispatcher.C index 61d359bef37..6077fff9335 100644 --- a/src/usr/initservice/istepdispatcher/istepdispatcher.C +++ b/src/usr/initservice/istepdispatcher/istepdispatcher.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2011,2019 */ +/* Contributors Listed Below - COPYRIGHT 2011,2020 */ /* [+] Google Inc. */ /* [+] International Business Machines Corp. */ /* */ @@ -1845,6 +1845,15 @@ void IStepDispatcher::requestPowerOff() // Send a power off message to the BMC (void)IPMI::initiatePowerOff(); } + +void IStepDispatcher::requestSoftPowerOff() +{ + // Always stop dispatching isteps before calling for the power off + INITSERVICE::stopIpl(); + + // Send a soft power off message to the BMC + (void)IPMI::initiateSoftPowerOff(); +} #endif // ---------------------------------------------------------------------------- // IStepDispatcher::shutdownDuringIpl() @@ -2764,6 +2773,11 @@ void requestPowerOff() { IStepDispatcher::getTheInstance().requestPowerOff(); } + +void requestSoftPowerOff() +{ + IStepDispatcher::getTheInstance().requestSoftPowerOff(); +} #endif diff --git a/src/usr/initservice/istepdispatcher/istepdispatcher.H b/src/usr/initservice/istepdispatcher/istepdispatcher.H index ea383c4c901..9cf36711a56 100644 --- a/src/usr/initservice/istepdispatcher/istepdispatcher.H +++ b/src/usr/initservice/istepdispatcher/istepdispatcher.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2011,2019 */ +/* Contributors Listed Below - COPYRIGHT 2011,2020 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -227,6 +227,11 @@ public: * @brief Trigger a power off via IPMI commands */ void requestPowerOff(); + + /** + * @brief Trigger a soft power off via IPMI commands + */ + void requestSoftPowerOff(); #endif /** diff --git a/src/usr/ipmibase/ipmirp.C b/src/usr/ipmibase/ipmirp.C index 152521cc084..ade6db6a5c4 100644 --- a/src/usr/ipmibase/ipmirp.C +++ b/src/usr/ipmibase/ipmirp.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2012,2019 */ +/* Contributors Listed Below - COPYRIGHT 2012,2020 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -461,18 +461,6 @@ void IpmiRP::handlePowerMessage( IPMI::oemSEL* i_event ) CONSOLE::flush(); #endif - } - // If the event type is a power soft reset, send a chasis reset - // update the modifier to send to the BMC - else if( i_event->iv_cmd[1] == IPMI::CHASSIS_POWER_SOFT_RESET ) - { - // handle the message as a power reset request - IPMI_TRAC("IPMI power reset request received"); - iv_chassis_power_mod = IPMI::CHASSIS_POWER_RESET; -#ifdef CONFIG_CONSOLE - CONSOLE::displayf(NULL, "IPMI: power cycle requested"); - CONSOLE::flush(); -#endif } else { @@ -725,16 +713,32 @@ void IpmiRP::execute(void) // begin a graceful reboot initiated by us case IPMI::MSG_STATE_INITIATE_POWER_CYCLE: + case IPMI::MSG_STATE_INITIATE_SOFT_POWER_OFF: { msg_free(msg); #ifdef CONFIG_CONSOLE - CONSOLE::displayf(NULL, "IPMI: Initiate power cycle"); + if (msg_type == IPMI::MSG_STATE_INITIATE_POWER_CYCLE) + { + CONSOLE::displayf(NULL, "IPMI: Initiate power cycle"); + } + else // == IPMI::MSG_STATE_INITIATE_SOFT_POWER_OFF + { + CONSOLE::displayf(NULL, "IPMI: Initiate soft power off"); + } CONSOLE::flush(); #endif // setup the power cmd modifier to tell the bmc to - // do a power reset - iv_chassis_power_mod = IPMI::CHASSIS_POWER_RESET; + // do a power reset or soft power off + if (msg_type == IPMI::MSG_STATE_INITIATE_POWER_CYCLE) + { + iv_chassis_power_mod = IPMI::CHASSIS_POWER_RESET; + } + else // == IPMI::MSG_STATE_INITIATE_SOFT_POWER_OFF + { + iv_chassis_power_mod = + IPMI::CHASSIS_POWER_SOFT_OFF_VIA_OVER_TEMP; + } // register for the post memory flush callback INITSERVICE::registerShutdownEvent(IPMI_COMP_ID, iv_msgQ, @@ -1100,6 +1104,11 @@ namespace IPMI (void)initiateShutdownOrReboot(MSG_STATE_GRACEFUL_SHUTDOWN); } + void initiateSoftPowerOff() + { + (void)initiateShutdownOrReboot(MSG_STATE_INITIATE_SOFT_POWER_OFF); + } + /// /// @brief Maximum buffer for data (max xport - header) /// diff --git a/src/usr/ipmiext/ipmisensor.C b/src/usr/ipmiext/ipmisensor.C index ae603235300..3c96fdbc956 100644 --- a/src/usr/ipmiext/ipmisensor.C +++ b/src/usr/ipmiext/ipmisensor.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2014,2019 */ +/* Contributors Listed Below - COPYRIGHT 2014,2020 */ /* [+] Google Inc. */ /* [+] International Business Machines Corp. */ /* */ @@ -1014,6 +1014,71 @@ namespace SENSOR return writeSensorData(); }; + // + // KeyClearRequestSensor constructor - uses system target + // + KeyClearRequestSensor::KeyClearRequestSensor() + :SensorBase(TARGETING::SENSOR_NAME_KEY_CLEAR_REQUEST, nullptr) + { + // message buffer created and initialized in base object. + + } + + // + // KeyClearRequestSensor destructor + // + KeyClearRequestSensor::~KeyClearRequestSensor(){}; + + // + // setKeyClearRequest - send a new value for the key clear request sensor + // to the BMC. + // + errlHndl_t KeyClearRequestSensor::setKeyClearRequest(const uint8_t i_value) + { + // This is a threshhhold sensor that sets one byte of data in the + // iv_sensor_reading field + iv_msg->iv_sensor_reading = i_value; + + return writeSensorData(); + } + + // + // getKeyClearRequest - Get the value of the key clear request sensor from the BMC + // + errlHndl_t KeyClearRequestSensor::getKeyClearRequest( uint8_t &o_value ) + { + // This is a threshhhold sensor that returns one byte of data in + // the sensor_status field + getSensorReadingData l_data; + + errlHndl_t l_err = readSensorData( l_data ); + + if( l_err == nullptr ) + { + o_value = l_data.sensor_status; + } + + // It's possible that the sensor_status byte being used as "data" has + // bits on that are treated as "status" and causing errors to be + // created in readSensorData. + // Look for that specific error and delete it, as the "data" should + // still be good + else if ((l_err->moduleId() == IPMI::MOD_IPMISENSOR) && + (l_err->reasonCode() == IPMI::RC_SENSOR_READING_NOT_AVAIL)) + { + o_value = l_data.sensor_status; + + TRACFCOMP(g_trac_ipmi, INFO_MRK "getKeyClearRequest() failed in " + "an expected way. Deleting this error and returning good " + "data 0x%.2X: " + TRACE_ERR_FMT, + o_value, TRACE_ERR_ARGS(l_err)); + delete l_err; + l_err = nullptr; + } + return l_err; + } + // // Used to update the sensor status for a specific set of target types // currently supported types are TYPE_DIMM, TYPE_MEMBUF, TYPE_CORE, diff --git a/src/usr/isteps/istep06/call_host_update_master_tpm.C b/src/usr/isteps/istep06/call_host_update_master_tpm.C index fa374f279ad..6a81c4ee100 100644 --- a/src/usr/isteps/istep06/call_host_update_master_tpm.C +++ b/src/usr/isteps/istep06/call_host_update_master_tpm.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015,2019 */ +/* Contributors Listed Below - COPYRIGHT 2015,2020 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -74,15 +74,12 @@ void* call_host_update_master_tpm( void *io_pArgs ) l_err = SECUREBOOT::detectPhysPresence(); if (l_err) { - // @TODO RTC 210301 - Handle Error Log Correctly, but for now - // just delete it TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "call_host_update_master_tpm: Error back from " - "SECUREBOOT::detectPhysPresence: rc=0x%X, plid=0x%X. " - "Deleting error for now", - ERRL_GETRC_SAFE(l_err), ERRL_GETPLID_SAFE(l_err)); - delete l_err; - l_err = nullptr; + "SECUREBOOT::detectPhysPresence: " + TRACE_ERR_FMT, + TRACE_ERR_ARGS(l_err)); + l_stepError.addErrorDetails(l_err); } #endif diff --git a/src/usr/isteps/istep10/call_host_update_redundant_tpm.C b/src/usr/isteps/istep10/call_host_update_redundant_tpm.C index 4f872f99557..ee0b1eda60f 100644 --- a/src/usr/isteps/istep10/call_host_update_redundant_tpm.C +++ b/src/usr/isteps/istep10/call_host_update_redundant_tpm.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015,2019 */ +/* Contributors Listed Below - COPYRIGHT 2015,2020 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -76,15 +76,12 @@ void* call_host_update_redundant_tpm (void *io_pArgs) l_err = SECUREBOOT::handlePhysPresenceWindow(); if (l_err) { - // @TODO RTC 210301 - Handle Error Log Correctly, but for now - // just delete it TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "call_host_update_redundant_tpm: Error back from " - "SECUREBOOT::handlePhysPresence: rc=0x%X, plid=0x%X. " - "Deleting error for now", - ERRL_GETRC_SAFE(l_err), ERRL_GETPLID_SAFE(l_err)); - delete l_err; - l_err = nullptr; + "SECUREBOOT::handlePhysPresence: " + TRACE_ERR_FMT, + TRACE_ERR_ARGS(l_err)); + l_istepError.addErrorDetails(l_err); } #endif diff --git a/src/usr/runtime/populate_hbruntime.C b/src/usr/runtime/populate_hbruntime.C index 57c1334661d..a3e8df7c98a 100644 --- a/src/usr/runtime/populate_hbruntime.C +++ b/src/usr/runtime/populate_hbruntime.C @@ -1992,10 +1992,18 @@ errlHndl_t populate_hbSecurebootData ( void ) l_elog = SECUREBOOT::clearKeyClearSensor(); if(l_elog != nullptr) { - TRACFCOMP( g_trac_runtime, ERR_MRK "populate_hbSecurebootData: " - "SECUREBOOT::clearKeyClearSensor() falied"); - break; - + l_elog->setSev(ERRORLOG::ERRL_SEV_INFORMATIONAL); + TRACFCOMP(g_trac_runtime, ERR_MRK "populate_hbSecurebootData: " + "SECUREBOOT::clearKeyClearSensor() falied. " + "Setting ERR to informational and committing here. " + "Don't want this fail to halt the IPL: " + TRACE_ERR_FMT, + TRACE_ERR_ARGS(l_elog)); + l_elog->collectTrace(SECURE_COMP_NAME); + l_elog->collectTrace(RUNTIME_COMP_NAME); + errlCommit(l_elog, RUNTIME_COMP_ID); + l_elog = nullptr; + // no "break;" - just continue } #endif // CONFIG_BMC_IPMI #endif // CONFIG_KEY_CLEAR diff --git a/src/usr/secureboot/ext/key_clear.C b/src/usr/secureboot/ext/key_clear.C index 42a5a022bcd..ad863699aca 100644 --- a/src/usr/secureboot/ext/key_clear.C +++ b/src/usr/secureboot/ext/key_clear.C @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -40,49 +41,150 @@ #include "../common/securetrace.H" #include // for getSbeSecurityBackdoor(); +#ifdef CONFIG_BMC_IPMI +#include +#endif + using namespace TARGETING; +using namespace ERRORLOG; namespace SECUREBOOT { #ifdef CONFIG_BMC_IPMI -errlHndl_t clearKeyClearSensor(void) +void getKeyClearRequestSensor(TARGETING::KEY_CLEAR_REQUEST & o_keyClearRequests) { errlHndl_t err = nullptr; + o_keyClearRequests = KEY_CLEAR_REQUEST_NONE; - // TODO RTC 210301 - Add Support for this function - SB_ENTER("clearKeyClearSensor"); - - SB_EXIT("clearKeyClearSensor: err rc=0x%X", - ERRL_GETRC_SAFE(err)); + SB_ENTER("getKeyClearRequestSensor"); - return err; -} + // The sensor has a size of one byte that maps to the MSB of the + // TARGETING::KEY_CLEAR_REQUEST struct (aka attribute) + uint8_t value = 0; + SENSOR::KeyClearRequestSensor sensor; -errlHndl_t getKeyClearRequestSensor( - TARGETING::KEY_CLEAR_REQUEST & o_keyClearRequests) -{ - errlHndl_t err = nullptr; + err = sensor.getKeyClearRequest( value ); + if ( err ) + { + err->setSev(ERRORLOG::ERRL_SEV_INFORMATIONAL); + SB_ERR("getKeyClearRequestSensor: FAIL Getting Key Clear Request Sensor" + ". Setting to ERRL_SEV_INFORMATIONAL and commiting it here: " + TRACE_ERR_FMT, + TRACE_ERR_ARGS(err)); + err->collectTrace( SECURE_COMP_NAME ); + errlCommit(err, SECURE_COMP_ID); - // TODO RTC 210301 - Add Support for this function - SB_ENTER("getKeyClearRequestSensor"); + } + else + { + // Need to shift the value 8 bits to the left to make it the MSBits of + // the o_keyClearRequests struct (aka attribute) + o_keyClearRequests = static_cast(value << 8); + } SB_EXIT("getKeyClearRequestSensor: err rc=0x%X, " "o_keyClearRequests = 0x%.04X", ERRL_GETRC_SAFE(err), o_keyClearRequests); + return; +} + +errlHndl_t clearKeyClearSensor(void) +{ + errlHndl_t err = nullptr; + TARGETING::KEY_CLEAR_REQUEST keyClearRequests = KEY_CLEAR_REQUEST_NONE; + + SB_ENTER("clearKeyClearSensor"); + + do + { + + // First Get Current Key Clear Request Sensor Value + getKeyClearRequestSensor(keyClearRequests); + + // Check if it needs to be cleared + if (keyClearRequests == KEY_CLEAR_REQUEST_NONE) + { + SB_INF("clearKeyClearSensor: no need to clear sensor as it is " + "already 0x%.4X", + keyClearRequests); + break; + } + + // Need to write zero back to sensor value + // NOTE: the sensor value is only a uint8_t whereas + // keyClearRequests is a uint16_t + uint8_t clear_value = 0; + SENSOR::KeyClearRequestSensor sensor; + + err = sensor.setKeyClearRequest( clear_value ); + if ( err ) + { + SB_ERR("clearKeyClearSensor: " + "FAIL Setting Key Clear Request Sensor: " + TRACE_ERR_FMT, + TRACE_ERR_ARGS(err)); + break; + } + + // Read back to make sure it's cleared + getKeyClearRequestSensor(keyClearRequests); + + // Check if it needs to be cleared + if (keyClearRequests == KEY_CLEAR_REQUEST_NONE) + { + SB_INF("clearKeyClearSensor: Key Clear Requests Sensor has been cleared"); + } + else + { + SB_ERR("clearKeyClearSensor: Failed to clear KeyClearRequestSensor: " + "Expected 0x%.4X, Actual 0x%.4X", + KEY_CLEAR_REQUEST_NONE, keyClearRequests); + + /*@ + * @errortype + * @reasoncode RC_CLEARING_KEY_CLEAR_SENSOR_FAILED + * @severity ERRL_SEV_UNRECOVERABLE + * @moduleid MOD_CLEAR_KEY_CLEAR_SENSOR + * @userdata1 Expected Key Clear Request Sensor Value + * @userdata2 Actual Key Clear Request Sensor Value + * @devdesc Attempt to clear the Key Clear Request Sensor + * failed as it still requests some keys to be cleared + * @custdesc A problem occurred during the IPL + * of the system. + */ + err = new ErrlEntry(ERRL_SEV_UNRECOVERABLE, + MOD_CLEAR_KEY_CLEAR_SENSOR, + RC_CLEARING_KEY_CLEAR_SENSOR_FAILED, + KEY_CLEAR_REQUEST_NONE, + keyClearRequests, + ErrlEntry::ADD_SW_CALLOUT); + + break; + + } + + } while(0); + + if (err) + { + err->collectTrace( SECURE_COMP_NAME ); + } + + SB_EXIT("clearKeyClearSensor: err rc=0x%X", + ERRL_GETRC_SAFE(err)); + return err; } + #endif // (#ifdef CONFIG_BMC_IPMI) #ifndef CONFIG_BMC_IPMI -static errlHndl_t getKeyClearRequestAttr( - TARGETING::KEY_CLEAR_REQUEST & o_keyClearRequests) +void getKeyClearRequestAttr(TARGETING::KEY_CLEAR_REQUEST & o_keyClearRequests) { - errlHndl_t err = nullptr; - SB_ENTER("getKeyClearRequestAttr"); // Get the attributes associated with Key Clear Requests @@ -93,21 +195,16 @@ static errlHndl_t getKeyClearRequestAttr( o_keyClearRequests = sys->getAttr(); - SB_EXIT("getKeyClearRequestAttr: err rc=0x%X, " - "o_keyClearRequests = 0x%.04X", - ERRL_GETRC_SAFE(err), + SB_EXIT("getKeyClearRequestAttr: o_keyClearRequests = 0x%.04X", o_keyClearRequests); - return err; + return; } #endif // (#ifndef CONFIG_BMC_IPMI) -errlHndl_t getKeyClearRequest( - bool & o_requestPhysPres, - TARGETING::KEY_CLEAR_REQUEST & o_keyClearRequests) +void getKeyClearRequest(bool & o_requestPhysPres, + TARGETING::KEY_CLEAR_REQUEST & o_keyClearRequests) { - errlHndl_t err = nullptr; - SB_ENTER("getKeyClearRequest"); o_requestPhysPres = false; @@ -127,30 +224,10 @@ errlHndl_t getKeyClearRequest( // Get Key Clear Request information #ifndef CONFIG_BMC_IPMI SB_DBG("getKeyClearRequest: calling getKeyClearRequestAttr"); - err = getKeyClearRequestAttr(l_keyClearRequests); - if(err) - { - SB_ERR("getKeyClearRequest: call to getKeyClearRequestAttr failed. " - "err_plid=0x%X, err_rc=0x%X", - ERRL_GETPLID_SAFE(err), - ERRL_GETRC_SAFE(err)); - - err->collectTrace(SECURE_COMP_NAME); - break; - } + getKeyClearRequestAttr(l_keyClearRequests); #else SB_DBG("getKeyClearRequest: calling getKeyClearRequestSensor"); - err = getKeyClearRequestSensor(l_keyClearRequests); - if(err) - { - SB_ERR("getKeyClearRequest: call to getKeyClearRequestSensor failed. " - "err_plid=0x%X, err_rc=0x%X", - ERRL_GETPLID_SAFE(err), - ERRL_GETRC_SAFE(err)); - - err->collectTrace(SECURE_COMP_NAME); - break; - } + getKeyClearRequestSensor(l_keyClearRequests); #endif // First check if the KEY_CLEAR_REQUEST_MFG bit is set and we have a @@ -207,16 +284,21 @@ errlHndl_t getKeyClearRequest( } } + // Set (potentially updated) Key Clear Requests attribute + TargetService& tS = targetService(); + Target* sys = nullptr; + (void) tS.getTopLevelTarget( sys ); + assert(sys, "getKeyClearRequest: system target is nullptr"); + sys->setAttr(l_keyClearRequests); + } while (0); - SB_EXIT("getKeyClearRequest: err rc=0x%X, " - "o_requestPhysPres = %s, " + SB_EXIT("getKeyClearRequest: o_requestPhysPres = %s, " "o_keyClearRequests = 0x%.04X", - ERRL_GETRC_SAFE(err), o_requestPhysPres ? "TRUE" : "FALSE", o_keyClearRequests); - return err; + return; } } // namespace SECUREBOOT diff --git a/src/usr/secureboot/ext/phys_presence.C b/src/usr/secureboot/ext/phys_presence.C index 74b137c28e7..203fa84c97d 100644 --- a/src/usr/secureboot/ext/phys_presence.C +++ b/src/usr/secureboot/ext/phys_presence.C @@ -38,12 +38,14 @@ #include #include #include +#include #include #include #include #include #include "../common/securetrace.H" #include +#include using namespace TARGETING; using namespace GPIO; @@ -77,6 +79,7 @@ errlHndl_t detectPhysPresence(void) uint8_t led_phys_pres_asserted = 0; bool is_window_open = false; bool is_phys_pres_asserted = false; + bool doesKeyClearRequestPhysPres = false; // Get the attributes associated with Physical Presence TargetService& tS = targetService(); @@ -100,15 +103,27 @@ errlHndl_t detectPhysPresence(void) attr_open_window, attr_open_window, attr_fake_assert, attr_fake_assert); + + // Get info associated with Key Clear Requests to see if physical presence + // detection is REALLY necessary + KEY_CLEAR_REQUEST keyClearRequests = KEY_CLEAR_REQUEST_NONE; +#ifdef CONFIG_KEY_CLEAR + getKeyClearRequest(doesKeyClearRequestPhysPres, keyClearRequests); + SB_INF("detectPhysPresence: call to getKeyClearRequest " + "returned: doesKeyClearRequestPhysPres=%d, " + "keyClearRequests=0x%.4X", + doesKeyClearRequestPhysPres,keyClearRequests); +#endif + // The PCA9551 device that controls the "window open" and // "physical presence asserted" logic is connected to the master processor err = targetService().queryMasterProcChipTargetHandle(mproc); if(err) { SB_ERR("detectPhysPresence: call to queryMasterProcChipTargetHandle " - "failed. err_plid=0x%X, err_rc=0x%X", - ERRL_GETPLID_SAFE(err), - ERRL_GETRC_SAFE(err)); + "failed. " + TRACE_ERR_FMT, + TRACE_ERR_ARGS(err)); err->collectTrace(SECURE_COMP_NAME); break; @@ -289,9 +304,21 @@ errlHndl_t detectPhysPresence(void) if (err_close) { + if (doesKeyClearRequestPhysPres == false) + { + err_close->setSev(ERRORLOG::ERRL_SEV_INFORMATIONAL); + SB_ERR("detectPhysPresence: Error in closing window. " + "Setting ERR to informational because we don't want a " + "physical presence detection err to halt the IPL if " + "there was no key clear request: " + TRACE_ERR_FMT, + TRACE_ERR_ARGS(err_close)); + err_close->collectTrace( SECURE_COMP_NAME ); + } + if (err) { - // commit new erro with PLID or original err + // commit new error with PLID of original err err_close->plid(err->plid()); SB_ERR("detectPhysPresence: Error in closing window. " "Committing err_close eid=0x%X " @@ -304,8 +331,8 @@ errlHndl_t detectPhysPresence(void) else { SB_ERR("detectPhysPresence: Error in closing window. " - "err_close eid=0x%X plid=0x%X", - err_close->eid(), err_close->plid()); + TRACE_ERR_FMT, + TRACE_ERR_ARGS(err)); err_close->collectTrace( SECURE_COMP_NAME ); err = err_close; err_close = nullptr; @@ -320,6 +347,23 @@ errlHndl_t detectPhysPresence(void) sys->setAttr(is_phys_pres_asserted); } + // If there is an error, but there was not a key clear request requiring + // the assertion of physical presence, make the error informational and + // commit it here so as not to halt the IPL + if ((err != nullptr) && + (doesKeyClearRequestPhysPres == false)) + { + err->setSev(ERRORLOG::ERRL_SEV_INFORMATIONAL); + SB_ERR("detectPhysPresence: Setting ERR to informational and " + "committing here. Don't want a physical presence detection " + "err to halt the IPL if there was no key clear request: " + TRACE_ERR_FMT, + TRACE_ERR_ARGS(err)); + err->collectTrace( SECURE_COMP_NAME ); + errlCommit(err, SECURE_COMP_ID); + err = nullptr; + } + SB_EXIT("detectPhysPresence: err rc=0x%X", ERRL_GETRC_SAFE(err)); @@ -339,6 +383,7 @@ errlHndl_t handlePhysPresenceWindow(void) ATTR_GPIO_INFO_PHYS_PRES_type gpioInfo = {}; uint8_t led_window_open = 0; bool is_window_open = false; + bool doesKeyClearRequestPhysPres = false; do { @@ -370,29 +415,22 @@ errlHndl_t handlePhysPresenceWindow(void) // Get info associated with Key Clear Requests - another possible reason // to open the Physical Presence Window - bool doesKeyClearRequestPhysPres = false; KEY_CLEAR_REQUEST keyClearRequests = KEY_CLEAR_REQUEST_NONE; #ifdef CONFIG_KEY_CLEAR - err = getKeyClearRequest(doesKeyClearRequestPhysPres, keyClearRequests); - if(err) - { - SB_ERR("handlePhysPresenceWindow: call to getKeyClearRequest " - "failed. err_plid=0x%X, err_rc=0x%X", - ERRL_GETPLID_SAFE(err), - ERRL_GETRC_SAFE(err)); - - err->collectTrace(SECURE_COMP_NAME); - break; - } - else - { - SB_INF("handlePhysPresenceWindow: call to getKeyClearRequest " - "returned: doesKeyClearRequestPhysPres=%d, " - "keyClearRequests=0x%X", - doesKeyClearRequestPhysPres,keyClearRequests); - } + getKeyClearRequest(doesKeyClearRequestPhysPres, keyClearRequests); + SB_INF("handlePhysPresenceWindow: call to getKeyClearRequest " + "returned: doesKeyClearRequestPhysPres=%d, " + "keyClearRequests=0x%X", + doesKeyClearRequestPhysPres,keyClearRequests); #endif + // Trace decision-related variables + SB_INF("handlePhysPresenceWindow: attr_open_window=0x%.2X, " + "doesKeyClearRequestPhysPres=%d, attr_phys_pres_asserted=0x%.2X, " + "attr_phys_pres_reipl=0x%.2X", + attr_open_window, doesKeyClearRequestPhysPres, + attr_phys_pres_asserted, attr_phys_pres_reipl); + // If physical presence is already asserted, then there's no need to open // the window if (attr_phys_pres_asserted != 0) @@ -463,9 +501,9 @@ errlHndl_t handlePhysPresenceWindow(void) if(err) { SB_ERR("handlePhysPresenceWindow: call to queryMasterProcChipTargetHandle " - "failed. err_plid=0x%X, err_rc=0x%X", - ERRL_GETPLID_SAFE(err), - ERRL_GETRC_SAFE(err)); + "failed. " + TRACE_ERR_FMT, + TRACE_ERR_ARGS(err)); err->collectTrace(SECURE_COMP_NAME); break; @@ -555,12 +593,18 @@ errlHndl_t handlePhysPresenceWindow(void) // Close request to open the window and sync attributes sys->setAttr(0x00); + attr_open_window = sys->getAttr(); // Set the attribute telling us that this re-IPL is purposely for // opening a physical presence window sys->setAttr(0x01); + attr_phys_pres_reipl = sys->getAttr(); + SB_INF("handlePhysPresenceWindow: Closing attr_open_window=0x0 (0x%.2X), " + "and setting ATTR_PHYS_PRES_REIPL to 0x01 (0x%.2X)", + attr_open_window, attr_phys_pres_reipl); + // Sync attributes for FSP systems if(INITSERVICE::spBaseServicesEnabled()) { // Sync all attributes to FSP before powering off @@ -571,9 +615,9 @@ errlHndl_t handlePhysPresenceWindow(void) // necessarily fatal. The power off will continue, // but this issue will be logged. SB_ERR("handlePhysPresenceWindow: Error syncing " - "attributes to FSP, RC=0x%04X, PLID=0x%08X", - ERRL_GETRC_SAFE(err), - ERRL_GETPLID_SAFE(err)); + "attributes to FSP. " + TRACE_ERR_FMT, + TRACE_ERR_ARGS(err)); errlCommit(err,SECURE_COMP_ID ); } } @@ -589,9 +633,8 @@ errlHndl_t handlePhysPresenceWindow(void) #ifdef CONFIG_BMC_IPMI // Initiate a graceful power off SB_INF("handlePhysPresenceWindow: Opened Physical Presence Detection Window. " - "System Will Power Off and Wait For Manual Power On. " - "Requesting power off"); - INITSERVICE::requestPowerOff(); + "System Will Power Off and Wait For Manual Power On"); + INITSERVICE::requestSoftPowerOff(); #else //non-IPMI SB_INF("handlePhysPresenceWindow: Opened Physical Presence Detection Window. " "Calling INITSERVICE::doShutdown() with " @@ -603,6 +646,23 @@ errlHndl_t handlePhysPresenceWindow(void) } while (0); + // If there is an error, but there was not a key clear request requiring + // the assertion of physical presence, make the error informational and + // commit it here so as not to halt the IPL + if ((err != nullptr) && + (doesKeyClearRequestPhysPres == false)) + { + err->setSev(ERRORLOG::ERRL_SEV_INFORMATIONAL); + SB_ERR("handlePhysPresenceWindow: Setting ERR to informational and " + "committing here. Don't want a physical presence detection " + "err to halt the IPL if there was no key clear request: " + TRACE_ERR_FMT, + TRACE_ERR_ARGS(err)); + err->collectTrace( SECURE_COMP_NAME ); + errlCommit(err, SECURE_COMP_ID); + err = nullptr; + } + SB_EXIT("handlePhysPresenceWindow: err_rc=0x%X", ERRL_GETRC_SAFE(err)); diff --git a/src/usr/targeting/common/xmltohb/attribute_types_hb.xml b/src/usr/targeting/common/xmltohb/attribute_types_hb.xml index f7e2c7450a1..369572a0b51 100755 --- a/src/usr/targeting/common/xmltohb/attribute_types_hb.xml +++ b/src/usr/targeting/common/xmltohb/attribute_types_hb.xml @@ -1309,7 +1309,7 @@ 0x0 - volatile-zeroed + non-volatile @@ -1556,6 +1556,10 @@ PCI_BIFURCATED 0xCD03 + + KEY_CLEAR_REQUEST + 0xCDD0 +