summaryrefslogtreecommitdiffstats
path: root/src/usr/ipmiext
diff options
context:
space:
mode:
Diffstat (limited to 'src/usr/ipmiext')
-rw-r--r--src/usr/ipmiext/ipmidcmi.C131
-rw-r--r--src/usr/ipmiext/ipmifruinv.C101
-rw-r--r--src/usr/ipmiext/ipmisensor.C93
-rw-r--r--src/usr/ipmiext/runtime/rt_ipmirp.C3
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>
OpenPOWER on IntegriCloud