Adding support to MCU reset boot reasons fixes jira https://jirasw.nvidia.com/browse/DGXOPENBMC-18081 Some more new MCU reset/boot reason are added support on NSM spec. This commit adding support to get all boot reason bit fields (256 bits) and decode that values to update it on dbus bootreason property. Signed-off-by: raghul r <raghulr@ami.com>
diff --git a/libnsm/diagnostics.c b/libnsm/diagnostics.c index e02c534..95a4140 100644 --- a/libnsm/diagnostics.c +++ b/libnsm/diagnostics.c
@@ -172,15 +172,19 @@ return NSM_SW_SUCCESS; } -int encode_reset_count_64data(uint64_t counter, uint8_t *data, size_t *data_len) +int encode_reset_count_256data(const uint64_t *counter, uint8_t *data, + size_t *data_len) { if (data == NULL || data_len == NULL) { return NSM_SW_ERROR_NULL; } - uint64_t le_count = htole64(counter); - memcpy(data, &le_count, sizeof(uint64_t)); - *data_len = sizeof(uint64_t); + for (size_t i = 0; i < 4; i++) { + uint64_t le_count = htole64(counter[i]); + memcpy(data + i * sizeof(uint64_t), &le_count, + sizeof(uint64_t)); + } + *data_len = sizeof(uint64_t) * 4; return NSM_SW_SUCCESS; } @@ -218,20 +222,23 @@ return NSM_SW_SUCCESS; } -int decode_reset_count_64data(const uint8_t *data, size_t data_len, - uint64_t *counter) +int decode_reset_count_256data(const uint8_t *data, size_t data_len, + uint64_t *counter, size_t counter_len) { - if (data == NULL || counter == NULL) { + if (data == NULL || counter == NULL || counter_len != 4) { return NSM_SW_ERROR_NULL; } - if (data_len != sizeof(uint64_t)) { + if (data_len != sizeof(uint64_t) * counter_len) { return NSM_SW_ERROR_LENGTH; } - uint64_t le_count; - memcpy(&le_count, data, sizeof(uint64_t)); - *counter = le64toh(le_count); + for (size_t i = 0; i < counter_len; i++) { + uint64_t le_count; + memcpy(&le_count, data + i * sizeof(uint64_t), + sizeof(uint64_t)); + counter[i] = le64toh(le_count); + } return NSM_SW_SUCCESS; }
diff --git a/libnsm/diagnostics.h b/libnsm/diagnostics.h index 0f5f6c4..03c274b 100644 --- a/libnsm/diagnostics.h +++ b/libnsm/diagnostics.h
@@ -292,7 +292,43 @@ uint64_t reserved29 : 1; uint64_t security_violation : 1; uint64_t tamper : 1; - uint64_t reserved32to63 : 32; + uint64_t iaccviol : 1; + uint64_t daccviol : 1; + uint64_t reserved34 : 1; + uint64_t munstkerr : 1; + uint64_t mstkerr : 1; + uint64_t reserved37to38 : 2; + uint64_t mmfarvalid : 1; + uint64_t bfarvalid : 1; + uint64_t reserved41to42 : 2; + uint64_t stkerr : 1; + uint64_t unstkerr : 1; + uint64_t imprecise_error : 1; + uint64_t precise_error : 1; + uint64_t ibuserr : 1; + uint64_t undefinstr : 1; + uint64_t invstate : 1; + uint64_t invpc : 1; + uint64_t nocp : 1; + uint64_t reserved52to55 : 4; + uint64_t unaligned : 1; + uint64_t devbyzero : 1; + uint64_t reserved58to64 : 7; + uint64_t vecttbl : 1; + uint64_t reserved66to93 : 28; + uint64_t forced : 1; + uint64_t debugevt : 1; + uint64_t mctp : 1; + uint64_t i2c : 1; + uint64_t i3c : 1; + uint64_t pldm : 1; + uint64_t usb : 1; + uint64_t flash : 1; + uint64_t logger : 1; + uint64_t spdm : 1; + uint64_t reserved104to127 : 24; + uint64_t reserved128to191 : 64; + uint64_t reserved192to255 : 64; } __attribute__((packed)); /** @brief Encode a Get device diagnostics request message @@ -705,13 +741,14 @@ /** * @brief Encodes a uint64 reset count into a byte array. * - * @param[in] count - Reset count as uint64_t. + * @param[in] count - Reset count as uint64_t array. * @param[out] data - Encoded byte array. * @param[out] data_len - Length of the encoded data. * * @return NSM_SW_SUCCESS on success, or appropriate error code. */ -int encode_reset_count_64data(uint64_t count, uint8_t *data, size_t *data_len); +int encode_reset_count_256data(const uint64_t *count, uint8_t *data, + size_t *data_len); /** * @brief Decodes a uint64 reset count from a byte array. @@ -719,11 +756,12 @@ * @param[in] data - Encoded byte array. * @param[in] data_len - Length of the encoded data. * @param[out] count - Decoded reset count as uint64_t. + * @param[in] count_len - Length of the decoded count. * * @return NSM_SW_SUCCESS on success, or appropriate error code. */ -int decode_reset_count_64data(const uint8_t *data, size_t data_len, - uint64_t *count); +int decode_reset_count_256data(const uint8_t *data, size_t data_len, + uint64_t *count, size_t count_len); /** * @brief Decodes a "Get Device Reset Statistics" request message.
diff --git a/libnsm/test/libnsm_diagnostics_test.cpp b/libnsm/test/libnsm_diagnostics_test.cpp index 0232dc4..785922d 100644 --- a/libnsm/test/libnsm_diagnostics_test.cpp +++ b/libnsm/test/libnsm_diagnostics_test.cpp
@@ -99,33 +99,34 @@ EXPECT_EQ(rc, NSM_SW_ERROR_LENGTH); } -// Tests for `encode_reset_count_64data` -TEST(ResetMetrics, EncodeResetCount64Data) +// Tests for `encode_reset_count_256data` +TEST(ResetMetrics, EncodeResetCount256Data) { - uint64_t count = 256; // Example count value - uint8_t data[8]; - size_t data_len; + std::array<uint64_t, 4> count = {256, 256, 256, + 256}; // Example count value + uint8_t data[32]; + size_t data_len = 0; - auto rc = encode_reset_count_64data(count, data, &data_len); + auto rc = encode_reset_count_256data(count.data(), data, &data_len); EXPECT_EQ(rc, NSM_SW_SUCCESS); - EXPECT_EQ(data_len, sizeof(uint64_t)); + EXPECT_EQ(data_len, sizeof(uint64_t) * 4); - uint64_t decodedCount; - memcpy(&decodedCount, data, sizeof(uint64_t)); - EXPECT_EQ(decodedCount, htole64(count)); + std::array<uint64_t, 4> decodedCount; + memcpy(decodedCount.data(), data, sizeof(uint64_t) * 4); + EXPECT_EQ(decodedCount, count); } -TEST(ResetMetrics, EncodeResetCount64DataNull) +TEST(ResetMetrics, EncodeResetCount256DataNull) { - uint64_t count = 256; + std::array<uint64_t, 4> count = {256, 256, 256, 256}; size_t data_len; - auto rc = encode_reset_count_64data(count, nullptr, &data_len); + auto rc = encode_reset_count_256data(count.data(), nullptr, &data_len); EXPECT_EQ(rc, NSM_SW_ERROR_NULL); - rc = encode_reset_count_64data(count, reinterpret_cast<uint8_t *>(0), - nullptr); + rc = encode_reset_count_256data( + count.data(), reinterpret_cast<uint8_t *>(0), nullptr); EXPECT_EQ(rc, NSM_SW_ERROR_NULL); } @@ -166,40 +167,48 @@ EXPECT_EQ(rc, NSM_SW_ERROR_NULL); } -// Tests for `decode_reset_count_64data` -TEST(ResetMetrics, DecodeResetCount64Data) +// Tests for `decode_reset_count_256data` +TEST(ResetMetrics, DecodeResetCount256Data) { - uint64_t count = 256; // Example encoded value - uint8_t data[8]; - memcpy(data, &count, sizeof(count)); - uint64_t decodedCount; + std::array<uint64_t, 4> count = {256, 256, 256, + 256}; // Example encoded value + uint8_t data[32]; + memcpy(data, count.data(), sizeof(count)); + std::array<uint64_t, 4> decodedCount; - auto rc = decode_reset_count_64data(data, sizeof(data), &decodedCount); + auto rc = decode_reset_count_256data(data, sizeof(data), + decodedCount.data(), 4); EXPECT_EQ(rc, NSM_SW_SUCCESS); - EXPECT_EQ(decodedCount, le64toh(count)); + EXPECT_EQ(decodedCount, count); + EXPECT_EQ(decodedCount[0], le64toh(count[0])); + EXPECT_EQ(decodedCount[1], le64toh(count[1])); + EXPECT_EQ(decodedCount[2], le64toh(count[2])); + EXPECT_EQ(decodedCount[3], le64toh(count[3])); } -TEST(ResetMetrics, DecodeResetCount64DataInvalidLength) +TEST(ResetMetrics, DecodeResetCount256DataInvalidLength) { - uint64_t count = 256; - uint8_t data[8]; - memcpy(data, &count, sizeof(count)); - uint64_t decodedCount; + std::array<uint64_t, 4> count = {256, 256, 256, + 256}; // Example encoded value + uint8_t data[32]; + memcpy(data, count.data(), sizeof(count)); + std::array<uint64_t, 4> decodedCount; - auto rc = - decode_reset_count_64data(data, sizeof(data) - 1, &decodedCount); + auto rc = decode_reset_count_256data(data, sizeof(data) - 1, + decodedCount.data(), 4); EXPECT_EQ(rc, NSM_SW_ERROR_LENGTH); } -TEST(ResetMetrics, DecodeResetCount64DataNull) +TEST(ResetMetrics, DecodeResetCount256DataNull) { - uint64_t decodedCount; - auto rc = decode_reset_count_64data(nullptr, 8, &decodedCount); + std::array<uint64_t, 4> decodedCount; + auto rc = + decode_reset_count_256data(nullptr, 32, decodedCount.data(), 4); EXPECT_EQ(rc, NSM_SW_ERROR_NULL); - uint8_t data[8] = {0}; - rc = decode_reset_count_64data(data, 8, nullptr); + uint8_t data[32] = {0}; + rc = decode_reset_count_256data(data, 32, nullptr, 4); EXPECT_EQ(rc, NSM_SW_ERROR_NULL); }
diff --git a/mockupResponder/mockupResponder.cpp b/mockupResponder/mockupResponder.cpp index 3176818..b11c272 100644 --- a/mockupResponder/mockupResponder.cpp +++ b/mockupResponder/mockupResponder.cpp
@@ -5237,10 +5237,10 @@ rc = encode_reset_enum_data(static_cast<uint8_t>(mockValue), reading, &sample_len); } - else if (tag == 8) // Special case for boot reason (uint64_t) + else if (tag == 8) // Special case for boot reason (256 bytes) { - rc = encode_reset_count_64data(static_cast<uint64_t>(mockValue), - reading, &sample_len); + rc = encode_reset_count_256data(bootReasonMockValue.data(), reading, + &sample_len); } else // General case for reset counts (uint16_t) {
diff --git a/mockupResponder/mockupResponder.hpp b/mockupResponder/mockupResponder.hpp index a293e24..da3ae53 100644 --- a/mockupResponder/mockupResponder.hpp +++ b/mockupResponder/mockupResponder.hpp
@@ -34,6 +34,7 @@ namespace MockupResponder { +const std::array<uint64_t, 4> bootReasonMockValue = {100, 548682072066, 0, 0}; const std::unordered_map<uint8_t, uint64_t> resetMetricsMockTable = { {0, 100}, // PF_FLR_ResetEntryCount
diff --git a/nsmd/nsmProcessor/nsmOemResetStatistics.cpp b/nsmd/nsmProcessor/nsmOemResetStatistics.cpp index 9841ba5..83b050e 100644 --- a/nsmd/nsmProcessor/nsmOemResetStatistics.cpp +++ b/nsmd/nsmProcessor/nsmOemResetStatistics.cpp
@@ -119,18 +119,19 @@ } else if (property == "BootReason") { - uint64_t counterVal; - if (decode_reset_count_64data(sample.data, sample.data_len, - &counterVal) != NSM_SW_SUCCESS) + std::array<uint64_t, 4> counterVal; + if (decode_reset_count_256data(sample.data, sample.data_len, + counterVal.data(), + counterVal.size()) != NSM_SW_SUCCESS) { lg2::error( - "Failed to decode ResetCount 64 data. Tag={TAG}, Data length={LEN}", + "Failed to decode ResetCount 256 data. Tag={TAG}, Data length={LEN}", "TAG", sample.tag, "LEN", sample.data_len); returnValue = NSM_SW_ERROR_LENGTH; continue; } - // Update property with uint64 value - updateProperty(property, counterVal); + // Update property with array of uint64 value + updateBootReasonProperty(property, counterVal); } else { @@ -252,60 +253,6 @@ auto resetType = static_cast<ResetCountersIntf::ResetTypes>(value); resetCountersIntf->lastResetType(resetType); } - else if (property == "BootReason") - { - // Convert and update enum array property - nsm_boot_reason_type_breakdown bootReason; - std::memcpy(&bootReason, &value, sizeof(bootReason)); - std::vector<BootReasonTypes> enabledReasons; - - if (bootReason.wake_up) - enabledReasons.emplace_back(BootReasonTypes::WakeUp); - if (bootReason.power_on) - enabledReasons.emplace_back(BootReasonTypes::PowerOn); - if (bootReason.voltage_detect) - enabledReasons.emplace_back(BootReasonTypes::VoltageDetect); - if (bootReason.warm_reset) - enabledReasons.emplace_back(BootReasonTypes::WarmReset); - if (bootReason.fatal_error) - enabledReasons.emplace_back(BootReasonTypes::FatalError); - if (bootReason.pin) - enabledReasons.emplace_back(BootReasonTypes::Pin); - if (bootReason.debug_access_port) - enabledReasons.emplace_back(BootReasonTypes::DebugAccessPort); - if (bootReason.reset_timeout) - enabledReasons.emplace_back(BootReasonTypes::ResetTimeout); - if (bootReason.low_power_acknowledge_timeout) - enabledReasons.emplace_back( - BootReasonTypes::LowPowerAcknowledgeTimeout); - if (bootReason.system_clock_generator) - enabledReasons.emplace_back( - BootReasonTypes::SystemClockGenerator); - if (bootReason.windowed_watchdog_0) - enabledReasons.emplace_back(BootReasonTypes::WindowedWatchdog0); - if (bootReason.software) - enabledReasons.emplace_back(BootReasonTypes::Software); - if (bootReason.lockup_reset) - enabledReasons.emplace_back(BootReasonTypes::LockupReset); - if (bootReason.cpu1) - enabledReasons.emplace_back(BootReasonTypes::CPU1); - if (bootReason.vbat) - enabledReasons.emplace_back(BootReasonTypes::VBAT); - if (bootReason.windowed_watchdog_1) - enabledReasons.emplace_back(BootReasonTypes::WindowedWatchdog1); - if (bootReason.code_watchdog_0) - enabledReasons.emplace_back(BootReasonTypes::CodeWatchdog0); - if (bootReason.code_watchdog_1) - enabledReasons.emplace_back(BootReasonTypes::CodeWatchdog1); - if (bootReason.jtag) - enabledReasons.emplace_back(BootReasonTypes::JTAG); - if (bootReason.security_violation) - enabledReasons.emplace_back(BootReasonTypes::SecurityViolation); - if (bootReason.tamper) - enabledReasons.emplace_back(BootReasonTypes::Tamper); - - resetCountersIntf->bootReason(enabledReasons); - } else { // Update numeric properties as double @@ -321,4 +268,124 @@ "PROPERTY", property, "VALUE", value, "ERROR", e.what()); } } + +void ResetStatisticsAggregator::updateBootReasonProperty( + const std::string& property, const std::array<uint64_t, 4>& value) +{ + try + { + // Convert and update enum array property + nsm_boot_reason_type_breakdown bootReason; + std::memcpy(&bootReason, &value, sizeof(bootReason)); + std::vector<BootReasonTypes> enabledReasons; + + if (bootReason.wake_up) + enabledReasons.emplace_back(BootReasonTypes::WakeUp); + if (bootReason.power_on) + enabledReasons.emplace_back(BootReasonTypes::PowerOn); + if (bootReason.voltage_detect) + enabledReasons.emplace_back(BootReasonTypes::VoltageDetect); + if (bootReason.warm_reset) + enabledReasons.emplace_back(BootReasonTypes::WarmReset); + if (bootReason.fatal_error) + enabledReasons.emplace_back(BootReasonTypes::FatalError); + if (bootReason.pin) + enabledReasons.emplace_back(BootReasonTypes::Pin); + if (bootReason.debug_access_port) + enabledReasons.emplace_back(BootReasonTypes::DebugAccessPort); + if (bootReason.reset_timeout) + enabledReasons.emplace_back(BootReasonTypes::ResetTimeout); + if (bootReason.low_power_acknowledge_timeout) + enabledReasons.emplace_back( + BootReasonTypes::LowPowerAcknowledgeTimeout); + if (bootReason.system_clock_generator) + enabledReasons.emplace_back(BootReasonTypes::SystemClockGenerator); + if (bootReason.windowed_watchdog_0) + enabledReasons.emplace_back(BootReasonTypes::WindowedWatchdog0); + if (bootReason.software) + enabledReasons.emplace_back(BootReasonTypes::Software); + if (bootReason.lockup_reset) + enabledReasons.emplace_back(BootReasonTypes::LockupReset); + if (bootReason.cpu1) + enabledReasons.emplace_back(BootReasonTypes::CPU1); + if (bootReason.vbat) + enabledReasons.emplace_back(BootReasonTypes::VBAT); + if (bootReason.windowed_watchdog_1) + enabledReasons.emplace_back(BootReasonTypes::WindowedWatchdog1); + if (bootReason.code_watchdog_0) + enabledReasons.emplace_back(BootReasonTypes::CodeWatchdog0); + if (bootReason.code_watchdog_1) + enabledReasons.emplace_back(BootReasonTypes::CodeWatchdog1); + if (bootReason.jtag) + enabledReasons.emplace_back(BootReasonTypes::JTAG); + if (bootReason.security_violation) + enabledReasons.emplace_back(BootReasonTypes::SecurityViolation); + if (bootReason.tamper) + enabledReasons.emplace_back(BootReasonTypes::Tamper); + if (bootReason.iaccviol) + enabledReasons.emplace_back(BootReasonTypes::IAccViol); + if (bootReason.daccviol) + enabledReasons.emplace_back(BootReasonTypes::DAccViol); + if (bootReason.munstkerr) + enabledReasons.emplace_back(BootReasonTypes::Munstkerr); + if (bootReason.mstkerr) + enabledReasons.emplace_back(BootReasonTypes::Mstkerr); + if (bootReason.mmfarvalid) + enabledReasons.emplace_back(BootReasonTypes::MMFarValid); + if (bootReason.bfarvalid) + enabledReasons.emplace_back(BootReasonTypes::BFarValid); + if (bootReason.stkerr) + enabledReasons.emplace_back(BootReasonTypes::Stkerr); + if (bootReason.unstkerr) + enabledReasons.emplace_back(BootReasonTypes::Unstkerr); + if (bootReason.imprecise_error) + enabledReasons.emplace_back(BootReasonTypes::ImpreciseError); + if (bootReason.precise_error) + enabledReasons.emplace_back(BootReasonTypes::PreciseError); + if (bootReason.ibuserr) + enabledReasons.emplace_back(BootReasonTypes::IBusErr); + if (bootReason.undefinstr) + enabledReasons.emplace_back(BootReasonTypes::UndefInstr); + if (bootReason.invstate) + enabledReasons.emplace_back(BootReasonTypes::InvState); + if (bootReason.invpc) + enabledReasons.emplace_back(BootReasonTypes::InvPC); + if (bootReason.nocp) + enabledReasons.emplace_back(BootReasonTypes::NoCP); + if (bootReason.unaligned) + enabledReasons.emplace_back(BootReasonTypes::Unaligned); + if (bootReason.devbyzero) + enabledReasons.emplace_back(BootReasonTypes::DevByZero); + if (bootReason.vecttbl) + enabledReasons.emplace_back(BootReasonTypes::VectTbl); + if (bootReason.forced) + enabledReasons.emplace_back(BootReasonTypes::Forced); + if (bootReason.debugevt) + enabledReasons.emplace_back(BootReasonTypes::DebugEvt); + if (bootReason.mctp) + enabledReasons.emplace_back(BootReasonTypes::MCTP); + if (bootReason.i2c) + enabledReasons.emplace_back(BootReasonTypes::I2C); + if (bootReason.i3c) + enabledReasons.emplace_back(BootReasonTypes::I3C); + if (bootReason.pldm) + enabledReasons.emplace_back(BootReasonTypes::PLDM); + if (bootReason.usb) + enabledReasons.emplace_back(BootReasonTypes::USB); + if (bootReason.flash) + enabledReasons.emplace_back(BootReasonTypes::Flash); + if (bootReason.logger) + enabledReasons.emplace_back(BootReasonTypes::Logger); + if (bootReason.spdm) + enabledReasons.emplace_back(BootReasonTypes::SPDM); + + resetCountersIntf->bootReason(enabledReasons); + } + catch (const std::exception& e) + { + lg2::error("Failed to update property {PROPERTY}: {ERROR}", "PROPERTY", + property, "ERROR", e.what()); + } +} + } // namespace nsm
diff --git a/nsmd/nsmProcessor/nsmOemResetStatistics.hpp b/nsmd/nsmProcessor/nsmOemResetStatistics.hpp index 42e7fca..a3c745b 100644 --- a/nsmd/nsmProcessor/nsmOemResetStatistics.hpp +++ b/nsmd/nsmProcessor/nsmOemResetStatistics.hpp
@@ -68,6 +68,10 @@ /** @brief Updates a D-Bus property with the provided value */ void updateProperty(const std::string& property, uint64_t value); + /** @brief Updates a D-Bus property with the provided value */ + void updateBootReasonProperty(const std::string& property, + const std::array<uint64_t, 4>& value); + // Mapping of tags to property names static const std::unordered_map<uint8_t, std::string> tagToPropertyMap;
diff --git a/nsmtool/nsm_diag_cmd.cpp b/nsmtool/nsm_diag_cmd.cpp index 4388db5..24173b3 100644 --- a/nsmtool/nsm_diag_cmd.cpp +++ b/nsmtool/nsm_diag_cmd.cpp
@@ -328,8 +328,9 @@ else if (property == "BootReason") { // Handle boot reason counter (uint64_t) - uint64_t counterVal; - if (decode_reset_count_64data(data, data_len, &counterVal) != + std::array<uint64_t, 4> counterVal; + if (decode_reset_count_256data( + data, data_len, counterVal.data(), counterVal.size()) != NSM_SW_SUCCESS) { return NSM_SW_ERROR_LENGTH; @@ -338,7 +339,10 @@ // Include the tag in the JSON sample_json["Tag"] = static_cast<int>(tag); sample_json["Property"] = property; - sample_json["Value"] = counterVal; + sample_json["Value0to63"] = counterVal[0]; + sample_json["Value64to127"] = counterVal[1]; + sample_json["Value128to191"] = counterVal[2]; + sample_json["Value192to255"] = counterVal[3]; } else {