xref: /openbmc/phosphor-power/tools/power-utils/model.cpp (revision 23dee383ca3a45889fbb4f7bbae65fe3325c5805)
10fbc2f6aSShawn McCarney /**
20fbc2f6aSShawn McCarney  * Copyright © 2024 IBM Corporation
30fbc2f6aSShawn McCarney  *
40fbc2f6aSShawn McCarney  * Licensed under the Apache License, Version 2.0 (the "License");
50fbc2f6aSShawn McCarney  * you may not use this file except in compliance with the License.
60fbc2f6aSShawn McCarney  * You may obtain a copy of the License at
70fbc2f6aSShawn McCarney  *
80fbc2f6aSShawn McCarney  *     http://www.apache.org/licenses/LICENSE-2.0
90fbc2f6aSShawn McCarney  *
100fbc2f6aSShawn McCarney  * Unless required by applicable law or agreed to in writing, software
110fbc2f6aSShawn McCarney  * distributed under the License is distributed on an "AS IS" BASIS,
120fbc2f6aSShawn McCarney  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130fbc2f6aSShawn McCarney  * See the License for the specific language governing permissions and
140fbc2f6aSShawn McCarney  * limitations under the License.
150fbc2f6aSShawn McCarney  */
160fbc2f6aSShawn McCarney #include "config.h"
170fbc2f6aSShawn McCarney 
180fbc2f6aSShawn McCarney #include "model.hpp"
190fbc2f6aSShawn McCarney 
200fbc2f6aSShawn McCarney #include "pmbus.hpp"
210fbc2f6aSShawn McCarney #include "utility.hpp"
220fbc2f6aSShawn McCarney #include "utils.hpp"
230fbc2f6aSShawn McCarney 
240fbc2f6aSShawn McCarney #include <nlohmann/json.hpp>
250fbc2f6aSShawn McCarney #include <phosphor-logging/log.hpp>
260fbc2f6aSShawn McCarney 
270fbc2f6aSShawn McCarney #include <exception>
280fbc2f6aSShawn McCarney #include <format>
290fbc2f6aSShawn McCarney #include <fstream>
300fbc2f6aSShawn McCarney #include <stdexcept>
310fbc2f6aSShawn McCarney 
320fbc2f6aSShawn McCarney using json = nlohmann::json;
330fbc2f6aSShawn McCarney 
340fbc2f6aSShawn McCarney using namespace utils;
350fbc2f6aSShawn McCarney using namespace phosphor::logging;
360fbc2f6aSShawn McCarney using namespace phosphor::power::util;
370fbc2f6aSShawn McCarney 
380fbc2f6aSShawn McCarney namespace model
390fbc2f6aSShawn McCarney {
400fbc2f6aSShawn McCarney 
410fbc2f6aSShawn McCarney namespace internal
420fbc2f6aSShawn McCarney {
430fbc2f6aSShawn McCarney 
440fbc2f6aSShawn McCarney /**
450fbc2f6aSShawn McCarney  * @brief Get the PSU model from sysfs.
460fbc2f6aSShawn McCarney  *
470fbc2f6aSShawn McCarney  * Obtain PSU information from the PSU JSON file.
480fbc2f6aSShawn McCarney  *
490fbc2f6aSShawn McCarney  * Throws an exception if an error occurs.
500fbc2f6aSShawn McCarney  *
510fbc2f6aSShawn McCarney  * @param[in] psuInventoryPath - PSU D-Bus inventory path
520fbc2f6aSShawn McCarney  *
530fbc2f6aSShawn McCarney  * @return PSU model
540fbc2f6aSShawn McCarney  */
getModelJson(const std::string & psuInventoryPath)550fbc2f6aSShawn McCarney std::string getModelJson(const std::string& psuInventoryPath)
560fbc2f6aSShawn McCarney {
570fbc2f6aSShawn McCarney     // Parse PSU JSON file
580fbc2f6aSShawn McCarney     std::ifstream file{PSU_JSON_PATH};
590fbc2f6aSShawn McCarney     json data = json::parse(file);
600fbc2f6aSShawn McCarney 
610fbc2f6aSShawn McCarney     // Get PSU device path from JSON
620fbc2f6aSShawn McCarney     auto it = data.find("psuDevices");
630fbc2f6aSShawn McCarney     if (it == data.end())
640fbc2f6aSShawn McCarney     {
650fbc2f6aSShawn McCarney         throw std::runtime_error{"Unable to find psuDevices"};
660fbc2f6aSShawn McCarney     }
670fbc2f6aSShawn McCarney     auto device = it->find(psuInventoryPath);
680fbc2f6aSShawn McCarney     if (device == it->end())
690fbc2f6aSShawn McCarney     {
700fbc2f6aSShawn McCarney         throw std::runtime_error{std::format(
710fbc2f6aSShawn McCarney             "Unable to find device path for PSU {}", psuInventoryPath)};
720fbc2f6aSShawn McCarney     }
730fbc2f6aSShawn McCarney     std::string devicePath = *device;
740fbc2f6aSShawn McCarney     if (devicePath.empty())
750fbc2f6aSShawn McCarney     {
760fbc2f6aSShawn McCarney         throw std::runtime_error{
770fbc2f6aSShawn McCarney             std::format("Empty device path for PSU {}", psuInventoryPath)};
780fbc2f6aSShawn McCarney     }
790fbc2f6aSShawn McCarney 
800fbc2f6aSShawn McCarney     // Get sysfs filename from JSON for Model information
810fbc2f6aSShawn McCarney     it = data.find("fruConfigs");
820fbc2f6aSShawn McCarney     if (it == data.end())
830fbc2f6aSShawn McCarney     {
840fbc2f6aSShawn McCarney         throw std::runtime_error{"Unable to find fruConfigs"};
850fbc2f6aSShawn McCarney     }
860fbc2f6aSShawn McCarney     std::string fileName;
870fbc2f6aSShawn McCarney     for (const auto& fru : *it)
880fbc2f6aSShawn McCarney     {
890fbc2f6aSShawn McCarney         if (fru.contains("propertyName") && (fru["propertyName"] == "Model") &&
900fbc2f6aSShawn McCarney             fru.contains("fileName"))
910fbc2f6aSShawn McCarney         {
920fbc2f6aSShawn McCarney             fileName = fru["fileName"];
930fbc2f6aSShawn McCarney             break;
940fbc2f6aSShawn McCarney         }
950fbc2f6aSShawn McCarney     }
960fbc2f6aSShawn McCarney     if (fileName.empty())
970fbc2f6aSShawn McCarney     {
980fbc2f6aSShawn McCarney         throw std::runtime_error{"Unable to find file name for Model"};
990fbc2f6aSShawn McCarney     }
1000fbc2f6aSShawn McCarney 
1010fbc2f6aSShawn McCarney     // Get PMBus access type from JSON
1020fbc2f6aSShawn McCarney     phosphor::pmbus::Type type = getPMBusAccessType(data);
1030fbc2f6aSShawn McCarney 
1040fbc2f6aSShawn McCarney     // Read model from sysfs file
1050fbc2f6aSShawn McCarney     phosphor::pmbus::PMBus pmbus(devicePath);
1060fbc2f6aSShawn McCarney     std::string model = pmbus.readString(fileName, type);
1070fbc2f6aSShawn McCarney     return model;
1080fbc2f6aSShawn McCarney }
1090fbc2f6aSShawn McCarney 
1100fbc2f6aSShawn McCarney /**
1110fbc2f6aSShawn McCarney  * @brief Get the PSU model from sysfs.
1120fbc2f6aSShawn McCarney  *
1130fbc2f6aSShawn McCarney  * Obtain PSU information from D-Bus.
1140fbc2f6aSShawn McCarney  *
1150fbc2f6aSShawn McCarney  * Throws an exception if an error occurs.
1160fbc2f6aSShawn McCarney  *
1170fbc2f6aSShawn McCarney  * @param[in] bus - D-Bus connection
1180fbc2f6aSShawn McCarney  * @param[in] psuInventoryPath - PSU D-Bus inventory path
1190fbc2f6aSShawn McCarney  *
1200fbc2f6aSShawn McCarney  * @return PSU model
1210fbc2f6aSShawn McCarney  */
getModelDbus(sdbusplus::bus_t & bus,const std::string & psuInventoryPath)1220fbc2f6aSShawn McCarney std::string getModelDbus(sdbusplus::bus_t& bus,
1230fbc2f6aSShawn McCarney                          const std::string& psuInventoryPath)
1240fbc2f6aSShawn McCarney {
1250fbc2f6aSShawn McCarney     // Get PSU I2C bus/address and create PMBus interface
1260fbc2f6aSShawn McCarney     const auto [i2cBus, i2cAddr] = getPsuI2c(bus, psuInventoryPath);
1270fbc2f6aSShawn McCarney     auto pmbus = getPmbusIntf(i2cBus, i2cAddr);
1280fbc2f6aSShawn McCarney 
1290fbc2f6aSShawn McCarney     // Read model from sysfs file
1300fbc2f6aSShawn McCarney     std::string fileName = "ccin";
1310fbc2f6aSShawn McCarney     auto type = phosphor::pmbus::Type::HwmonDeviceDebug;
1320fbc2f6aSShawn McCarney     std::string model = pmbus->readString(fileName, type);
1330fbc2f6aSShawn McCarney     return model;
1340fbc2f6aSShawn McCarney }
1350fbc2f6aSShawn McCarney 
1360fbc2f6aSShawn McCarney } // namespace internal
1370fbc2f6aSShawn McCarney 
getModel(sdbusplus::bus_t & bus,const std::string & psuInventoryPath)1380fbc2f6aSShawn McCarney std::string getModel(sdbusplus::bus_t& bus, const std::string& psuInventoryPath)
1390fbc2f6aSShawn McCarney {
1400fbc2f6aSShawn McCarney     std::string model;
1410fbc2f6aSShawn McCarney     try
1420fbc2f6aSShawn McCarney     {
143*23dee383SShawn McCarney         if (usePsuJsonFile())
1440fbc2f6aSShawn McCarney         {
1450fbc2f6aSShawn McCarney             // Obtain PSU information from JSON file
1460fbc2f6aSShawn McCarney             model = internal::getModelJson(psuInventoryPath);
1470fbc2f6aSShawn McCarney         }
1480fbc2f6aSShawn McCarney         else
1490fbc2f6aSShawn McCarney         {
1500fbc2f6aSShawn McCarney             // Obtain PSU information from D-Bus
1510fbc2f6aSShawn McCarney             model = internal::getModelDbus(bus, psuInventoryPath);
1520fbc2f6aSShawn McCarney         }
1530fbc2f6aSShawn McCarney     }
1540fbc2f6aSShawn McCarney     catch (const std::exception& e)
1550fbc2f6aSShawn McCarney     {
1560fbc2f6aSShawn McCarney         log<level::ERR>(std::format("Error: {}", e.what()).c_str());
1570fbc2f6aSShawn McCarney     }
1580fbc2f6aSShawn McCarney     return model;
1590fbc2f6aSShawn McCarney }
1600fbc2f6aSShawn McCarney 
1610fbc2f6aSShawn McCarney } // namespace model
162