Added IPMI handler to support core count request
This change introduces a new OEM IPMI command (#30 - SysGetCoreCount)
to allow the BIOS or host to query the number of CPU cores as reported
by the BMC.
The core count is read from /run/cpu_config.json on the BMC. If the file
is not found or invalid, the command will return an error or 0 cores.
This is needed for the BIOS to dynamically adjust settings based on the
CPU configuration .
Tested:
{
"cpu_core_count": 255
}
root@ddcgq3-nfd01:/# ipmitool raw 0x2e 0x32 0x79 0x2b 0x00 0x1a
79 2b 00 1a ff 00
79 2b 00 1a 00 01
{
"cpu_core_count": 256
}
cat /run/cpu_config.json
{
"cpu_core_count": 320
}
79 2b 00 1a 40 01
Change-Id: I946d5ac918a2dae8a94e1b348446075e72007e3e
Signed-off-by: Vikram Gara <vikramgara+bmc@google.com>
diff --git a/handler.cpp b/handler.cpp
index 18c74a1..57a5e5a 100644
--- a/handler.cpp
+++ b/handler.cpp
@@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#include "config.h"
+
#include "handler.hpp"
#include "bm_config.h"
@@ -42,6 +44,7 @@
#include <fstream>
#include <iomanip>
#include <map>
+#include <optional>
#include <sstream>
#include <string>
#include <string_view>
@@ -807,8 +810,65 @@
stdplus::print(stderr, "Failed to read: '{}'.\n", opath);
throw IpmiException(::ipmi::ccUnspecifiedError);
}
+
return property;
}
+std::optional<uint16_t> Handler::getCoreCount(const std::string& filePath) const
+{
+ std::error_code ec;
+ if (!this->getFs()->exists(filePath, ec))
+ {
+ log<level::INFO>("CPU config file not found",
+ entry("PATH=%s", filePath.c_str()));
+ return std::nullopt;
+ }
+
+ std::ifstream ifs(filePath);
+ if (!ifs.is_open())
+ {
+ log<level::ERR>("Failed to open CPU config file",
+ entry("PATH=%s", filePath.c_str()));
+ return std::nullopt;
+ }
+
+ try
+ {
+ Json data = Json::parse(ifs);
+ if (data.contains("cpu_core_count") &&
+ data["cpu_core_count"].is_number_integer())
+ {
+ int coreCountInt = data["cpu_core_count"].get<int>();
+ if (coreCountInt < 0 || coreCountInt > UINT16_MAX)
+ {
+ log<level::ERR>("Core count out of range for uint16_t",
+ entry("PATH=%s", filePath.c_str()),
+ entry("VALUE=%d", coreCountInt));
+ return std::nullopt;
+ }
+ return static_cast<uint16_t>(coreCountInt);
+ }
+ else
+ {
+ log<level::ERR>("Invalid format in CPU config file",
+ entry("PATH=%s", filePath.c_str()));
+ return std::nullopt;
+ }
+ }
+ catch (Json::parse_error& e)
+ {
+ log<level::ERR>("Failed to parse CPU config file",
+ entry("PATH=%s", filePath.c_str()),
+ entry("WHAT=%s", e.what()));
+ return std::nullopt;
+ }
+ catch (...)
+ {
+ log<level::ERR>("Unknown error reading CPU config file",
+ entry("PATH=%s", filePath.c_str()));
+ return std::nullopt;
+ }
+}
+
} // namespace ipmi
} // namespace google