diff options
Diffstat (limited to 'src/usr/ipmiext')
-rw-r--r-- | src/usr/ipmiext/ipmidcmi.C | 131 | ||||
-rw-r--r-- | src/usr/ipmiext/ipmifruinv.C | 101 | ||||
-rw-r--r-- | src/usr/ipmiext/ipmisensor.C | 93 | ||||
-rw-r--r-- | src/usr/ipmiext/runtime/rt_ipmirp.C | 3 |
4 files changed, 245 insertions, 83 deletions
diff --git a/src/usr/ipmiext/ipmidcmi.C b/src/usr/ipmiext/ipmidcmi.C index 24f192d29..b3f9d1e22 100644 --- a/src/usr/ipmiext/ipmidcmi.C +++ b/src/usr/ipmiext/ipmidcmi.C @@ -5,8 +5,9 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015,2018 */ +/* Contributors Listed Below - COPYRIGHT 2015,2019 */ /* [+] International Business Machines Corp. */ +/* [+] Maxim Polyakov */ /* */ /* */ /* Licensed under the Apache License, Version 2.0 (the "License"); */ @@ -34,6 +35,8 @@ #include <ipmi/ipmi_reasoncodes.H> extern trace_desc_t * g_trac_ipmi; +#define DCMI_CAP_RESPONSE_DATA_LENGTH 7 + namespace SENSOR { enum dcmi_cc @@ -42,6 +45,107 @@ namespace SENSOR POWER_LIMIT_NOT_ACTIVE = 0x80, }; + static errlHndl_t getPowerManagementSupportStatus(bool &support) + { + errlHndl_t err = NULL; + IPMI::completion_code cc = IPMI::CC_UNKBAD; + + support = false; + + size_t len = 2; + uint8_t* data = new uint8_t[len]; + data[0] = 0xDC; // Group Extension Identification + data[1] = 0x01; // Selector - Supported DCMI Capabilities + + err = IPMI::sendrecv(IPMI::get_dcmi_capability_info(), cc, len, data); + do + { + if (err) + { + TRACFCOMP(g_trac_ipmi, + "Failed to send DCMI Capabilities Command to BMC"); + break; + } + + if (cc != IPMI::CC_OK) + { + TRACFCOMP(g_trac_ipmi, + "Get DCMI Capabilities Command: " + "bad completion code from BMC=0x%x", + cc); + + /*@ + * @errortype ERRL_SEV_INFORMATIONAL + * @moduleid IPMI::MOD_IPMIDCMI + * @reasoncode IPMI::RC_GET_DCMI_CAP_CMD_FAILED + * @userdata1 BMC IPMI Completion code. + * @devdesc Request to get DCMI Capabilities information + * failed + * @custdesc The DCMI Capabilities Info Command retrieve + * data from the BMC has failed. + * + */ + + err = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_INFORMATIONAL, + IPMI::MOD_IPMIDCMI, + IPMI::RC_GET_DCMI_CAP_CMD_FAILED, + static_cast<uint64_t>(cc), + 0, + true); + break; + } + + if (len != DCMI_CAP_RESPONSE_DATA_LENGTH) + { + TRACFCOMP(g_trac_ipmi, + "Get DCMI Capabilities Command: " + "invalid data length=%d", + len); + + /*@ + * @errortype ERRL_SEV_INFORMATIONAL + * @moduleid IPMI::MOD_IPMIDCMI + * @reasoncode IPMI::RC_INVALID_QRESPONSE + * @userdata1 Response data length. + * @devdesc Request to get DCMI Capabilities information + * failed + * @custdesc The DCMI Capabilities Info Command retrieve + * data with invalid length. + * + */ + + err = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_INFORMATIONAL, + IPMI::MOD_IPMIDCMI, + IPMI::RC_INVALID_QRESPONSE, + static_cast<uint64_t>(len), + 0, + true); + break; + } + + // from the DCMI spec v1.5, Revision 1.0, August 23, 2011 + // DCMI Capabilities Response Command Format: + // cc: byte 1 completion code + // data: + // data[0]: byte 1 0xDC + // data[1]: byte 2 Major Version (01h) + // data[2]: byte 3 Minor Version (05h) + // data[3]: byte 4 Parameter Revision (02h) + // data[4]: byte 5 Reserved + // data[5]: byte 6 Platform capabilities + // [7:1] Reserved + // [0] Power management + // data[6]: byte 7 Manageability Access Capabilities + support = !!(data[5] & 0x1); + + } while(false); + + delete[] data; + return err; + } + // fetch the user defined power limit stored on the BMC // using the DCMI Get Power Limit command errlHndl_t getUserPowerLimit( uint16_t &o_powerLimit, bool &o_limitActive ) @@ -53,6 +157,31 @@ namespace SENSOR errlHndl_t l_err = NULL; + // Power Management support check + bool support; + l_err = getPowerManagementSupportStatus(support); + if (l_err != NULL) + { + // Since the Power Management support information isn`t received, + // commit this error and still try to read the power limit. If the + // Power Management is really unsupported, the DCMI Get Power Limit + // command will return error code in l_cc + l_err->collectTrace(IPMI_COMP_NAME); + errlCommit(l_err, IPMI_COMP_ID); + + TRACFCOMP(g_trac_ipmi, + "Failed to determine if the BMC supports Power Management"); + + support = true; + } + + if (!support) + { + TRACFCOMP(g_trac_ipmi, + "Power Management is not supported by BMC"); + return NULL; + } + // per DCMI spec data size is 3 bytes size_t len = 3; diff --git a/src/usr/ipmiext/ipmifruinv.C b/src/usr/ipmiext/ipmifruinv.C index e70d5afa0..14ad957d1 100644 --- a/src/usr/ipmiext/ipmifruinv.C +++ b/src/usr/ipmiext/ipmifruinv.C @@ -7,8 +7,9 @@ /* */ /* Contributors Listed Below - COPYRIGHT 2014,2019 */ /* [+] International Business Machines Corp. */ -/* [+] Jim Yuan */ -/* [+] Maxim Polyakov */ +/* [+] Super Micro Computer, Inc. */ +/* [+] YADRO */ +/* [+] lixg */ /* */ /* */ /* Licensed under the Apache License, Version 2.0 (the "License"); */ @@ -546,42 +547,43 @@ errlHndl_t IpmiFruInv::formatMfgData(std::vector<uint8_t> i_mfgDateData, { errlHndl_t l_errl = NULL; - // MB keyword size is 8 hex bytes, throw an error if it is smaller so we - // don't do an invalid access. - if (i_mfgDateData.size() != 8) + do { - /*@ - * @errortype - * @moduleid IPMI::MOD_IPMIFRU_INV - * @reasoncode IPMI::RC_INVALID_VPD_DATA - * @userdata1 Size of vpd data - * - * @devdesc VPD data is invalid size - */ - l_errl = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_INFORMATIONAL, - IPMI::MOD_IPMIFRU_INV, - IPMI::RC_INVALID_VPD_DATA, - i_mfgDateData.size()); - - TARGETING::Target* nodeTarget = NULL; - TARGETING::PredicateCTM nodeFilter(TARGETING::CLASS_ENC, - TARGETING::TYPE_NODE); - TARGETING::TargetRangeFilter nodeItr( - TARGETING::targetService().begin(), - TARGETING::targetService().end(), - &nodeFilter); - - nodeTarget = *nodeItr; - - // Callout out node since that is where the VPD lives - l_errl->addHwCallout(nodeTarget, - HWAS::SRCI_PRIORITY_HIGH, - HWAS::NO_DECONFIG, - HWAS::GARD_NULL ); + // MB keyword size is 8 hex bytes, throw an error if it is smaller so we + // don't do an invalid access. + if (i_mfgDateData.size() != 8) + { + /*@ + * @errortype + * @moduleid IPMI::MOD_IPMIFRU_INV + * @reasoncode IPMI::RC_INVALID_VPD_DATA + * @userdata1 Size of vpd data + * + * @devdesc VPD data is invalid size + */ + l_errl = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_INFORMATIONAL, + IPMI::MOD_IPMIFRU_INV, + IPMI::RC_INVALID_VPD_DATA, + i_mfgDateData.size()); + + TARGETING::Target* nodeTarget = NULL; + TARGETING::PredicateCTM nodeFilter(TARGETING::CLASS_ENC, + TARGETING::TYPE_NODE); + TARGETING::TargetRangeFilter nodeItr( + TARGETING::targetService().begin(), + TARGETING::targetService().end(), + &nodeFilter); + + nodeTarget = *nodeItr; + + // Callout out node since that is where the VPD lives + l_errl->addHwCallout(nodeTarget, + HWAS::SRCI_PRIORITY_HIGH, + HWAS::NO_DECONFIG, + HWAS::GARD_NULL ); + break; + } - } - else - { // Convert Centuries / Years / months / day / hour / minute / second // into a uint64 representing number of minute since 1/1/96 @@ -594,6 +596,25 @@ errlHndl_t IpmiFruInv::formatMfgData(std::vector<uint8_t> i_mfgDateData, uint8_t hour = bcd2_to_int(i_mfgDateData.at(5)); uint8_t minute = bcd2_to_int(i_mfgDateData.at(6)); + // Do some sanity checking on the data so the math below doesn't + // go crazy and cause a crash + if ( (century < 20) + || (month < 1) || (month > 12) + || (day < 1) || (day > 31) + || (hour > 23) || (minute > 59) ) + { + o_mfgDate = 0xFFFFFFFF; + TRACFCOMP(g_trac_ipmi,"MfgDate error: %02X %02X %02X %02X %02X %02X %02X ", + i_mfgDateData.at(0), + i_mfgDateData.at(1), + i_mfgDateData.at(2), + i_mfgDateData.at(3), + i_mfgDateData.at(4), + i_mfgDateData.at(5), + i_mfgDateData.at(6)); + break; + } + // Subtract year uint8_t numOfYears = (century*100 + year) - 1996; // Subtract month @@ -612,6 +633,7 @@ errlHndl_t IpmiFruInv::formatMfgData(std::vector<uint8_t> i_mfgDateData, // Add a day for every leap year // Check if we need to consider the current year + // Year is related to century, anybody familiar with this may fix it if (month <= 2) { // We don't need to consider this year for a leap year, as it @@ -638,7 +660,7 @@ errlHndl_t IpmiFruInv::formatMfgData(std::vector<uint8_t> i_mfgDateData, // Convert into minutes o_mfgDate = (((numOfDays*24)*60) + (hour*60) + minute); - } + } while(0); return l_errl; } @@ -2406,6 +2428,8 @@ void IPMIFRUINV::gatherSetData(const TARGETING::Target* i_pSys, TARGETING::PredicateCTM predChip(TARGETING::CLASS_CHIP); TARGETING::PredicateCTM predDimm(TARGETING::CLASS_LOGICAL_CARD, TARGETING::TYPE_DIMM); + TARGETING::PredicateCTM predOcmb(TARGETING::CLASS_CHIP, + TARGETING::TYPE_OCMB_CHIP); TARGETING::PredicatePostfixExpr checkExpr; TARGETING::PredicateHwas l_present; // @todo-RTC:124553 - Additional logic for deconfigured Frus @@ -2427,6 +2451,9 @@ void IPMIFRUINV::gatherSetData(const TARGETING::Target* i_pSys, checkExpr.push(&predDimm).Or().push(&l_present).And(); } + // We do NOT want to process fruInv for OCMB_CHIP targets + checkExpr.push(&predOcmb).Not().And(); + TARGETING::TargetHandleList pCheckPres; TARGETING::targetService().getAssociated( pCheckPres, i_pSys, TARGETING::TargetService::CHILD, TARGETING::TargetService::ALL, diff --git a/src/usr/ipmiext/ipmisensor.C b/src/usr/ipmiext/ipmisensor.C index 5dd428d06..ae6032353 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,2018 */ +/* Contributors Listed Below - COPYRIGHT 2014,2019 */ /* [+] Google Inc. */ /* [+] International Business Machines Corp. */ /* */ @@ -1363,7 +1363,7 @@ namespace SENSOR TARGETING::targetService().getTopLevelTarget(sys); assert(sys != NULL); getChildAffinityTargets(nodes, sys, TARGETING::CLASS_ENC, - TARGETING::TYPE_NODE); + TARGETING::TYPE_NODE, false); assert(!nodes.empty()); //Backplane sensor ID @@ -1390,8 +1390,13 @@ namespace SENSOR static uint16_t L_NV_bits = 0; errlHndl_t l_err = nullptr; - if (L_NV_bits == 0) - { + do { + // only do the lookup once + if (L_NV_bits != 0) + { + break; + } + // grab system enclosure node TARGETING::TargetHandle_t l_sys = NULL; TARGETING::TargetHandleList l_nodeTargets; @@ -1399,61 +1404,63 @@ namespace SENSOR assert(l_sys != NULL); getChildAffinityTargets(l_nodeTargets, l_sys, TARGETING::CLASS_ENC, TARGETING::TYPE_NODE); - assert(!l_nodeTargets.empty()); + if(l_nodeTargets.empty()) + { + TRACFCOMP(g_trac_ipmi,"getNVCfgIDBit(): No functional nodes - forcing invalid config"); + break; + } // get keyword size first PVPD::pvpdRecord l_Record = PVPD::VNDR; PVPD::pvpdKeyword l_KeyWord = PVPD::NV; size_t l_nvKwdSize = 0; l_err = deviceRead(l_nodeTargets[0],NULL,l_nvKwdSize, - DEVICE_PVPD_ADDRESS(l_Record,l_KeyWord)); - if (!l_err) + DEVICE_PVPD_ADDRESS(l_Record,l_KeyWord)); + if (l_err) { - if (l_nvKwdSize == sizeof(HDAT::hdatNVKwdStruct_t)) + TRACFCOMP(g_trac_ipmi,"getNVCfgIDBit(): Error getting VNDR:NV size"); + break; + } + + if (l_nvKwdSize != sizeof(HDAT::hdatNVKwdStruct_t)) + { + TRACFCOMP(g_trac_ipmi,"Invalid NV keyword size: %d, expected %d",l_nvKwdSize,sizeof(HDAT::hdatNVKwdStruct_t)); + break; + } + + uint8_t l_kwd[l_nvKwdSize] = {0}; + // now read the keyword + l_err = deviceRead(l_nodeTargets[0],l_kwd,l_nvKwdSize, + DEVICE_PVPD_ADDRESS(l_Record,l_KeyWord)); + if (l_err) + { + TRACFCOMP(g_trac_ipmi,"getNVCfgIDBit(): Error reading VNDR:NV"); + break; + } + + HDAT::hdatNVKwdStruct_t * NVptr = + reinterpret_cast<HDAT::hdatNVKwdStruct_t*>(l_kwd); + + // Valid NV keyword config has NV00 as magic header + if ( !memcmp((char*)&(NVptr->magic),"NV00", 4) ) + { + uint8_t cfgID = NVptr->config; + if (cfgID < 16) // maximum setting (bits 0-15) { - uint8_t l_kwd[l_nvKwdSize] = {0}; - // now read the keyword - l_err = deviceRead(l_nodeTargets[0],l_kwd,l_nvKwdSize, - DEVICE_PVPD_ADDRESS(l_Record,l_KeyWord)); - if (!l_err) - { - HDAT::hdatNVKwdStruct_t * NVptr = - reinterpret_cast<HDAT::hdatNVKwdStruct_t*>(l_kwd); - - // Valid NV keyword config has NV00 as magic header - if ( !memcmp((char*)&(NVptr->magic),"NV00", 4) ) - { - uint8_t cfgID = NVptr->config; - if (cfgID < 16) // maximum setting (bits 0-15) - { - L_NV_bits = 0x0001 << cfgID; - } - else - { - TRACFCOMP(g_trac_ipmi,"getNVCfgIDBit(): Invalid NV config 0x%02X", cfgID); - } - } - else - { - TRACFCOMP(g_trac_ipmi, "Invalid NV magic header: 0x%.8X", NVptr->magic); - TRACFBIN(g_trac_ipmi, "NV KEYWORD", l_kwd, l_nvKwdSize); - } - } - else - { - TRACFCOMP(g_trac_ipmi,ERR_MRK"%.8X Error getting VNDR record data",l_err->eid()); - } + L_NV_bits = 0x0001 << cfgID; } else { - TRACFCOMP(g_trac_ipmi,"Invalid NV keyword size: %d, expected %d",l_nvKwdSize,sizeof(HDAT::hdatNVKwdStruct_t)); + TRACFCOMP(g_trac_ipmi,"getNVCfgIDBit(): Invalid NV config 0x%02X", cfgID); + break; } } else { - TRACFCOMP(g_trac_ipmi,ERR_MRK"%.8X Error getting VNDR record size",l_err->eid()); + TRACFCOMP(g_trac_ipmi, "Invalid NV magic header: 0x%.8X", NVptr->magic); + TRACFBIN(g_trac_ipmi, "NV KEYWORD", l_kwd, l_nvKwdSize); } - } + } while(0); o_cfgID_bitwise = L_NV_bits; diff --git a/src/usr/ipmiext/runtime/rt_ipmirp.C b/src/usr/ipmiext/runtime/rt_ipmirp.C index 496b3f782..83b4d9b10 100644 --- a/src/usr/ipmiext/runtime/rt_ipmirp.C +++ b/src/usr/ipmiext/runtime/rt_ipmirp.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015,2018 */ +/* Contributors Listed Below - COPYRIGHT 2015,2019 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -30,7 +30,6 @@ #include <ipmi/ipmi_reasoncodes.H> #include <ipmi/ipmiif.H> -#include <config.h> #include <sys/task.h> #include <initservice/taskargs.H> #include <initservice/initserviceif.H> |