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