xref: /openbmc/phosphor-logging/extensions/openpower-pels/device_callouts.cpp (revision a307089cb7b562ab7c6d8f14142b549510821978)
118c42b0fSMatt Spinler /**
218c42b0fSMatt Spinler  * Copyright © 2020 IBM Corporation
318c42b0fSMatt Spinler  *
418c42b0fSMatt Spinler  * Licensed under the Apache License, Version 2.0 (the "License");
518c42b0fSMatt Spinler  * you may not use this file except in compliance with the License.
618c42b0fSMatt Spinler  * You may obtain a copy of the License at
718c42b0fSMatt Spinler  *
818c42b0fSMatt Spinler  *     http://www.apache.org/licenses/LICENSE-2.0
918c42b0fSMatt Spinler  *
1018c42b0fSMatt Spinler  * Unless required by applicable law or agreed to in writing, software
1118c42b0fSMatt Spinler  * distributed under the License is distributed on an "AS IS" BASIS,
1218c42b0fSMatt Spinler  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1318c42b0fSMatt Spinler  * See the License for the specific language governing permissions and
1418c42b0fSMatt Spinler  * limitations under the License.
1518c42b0fSMatt Spinler  */
1618c42b0fSMatt Spinler #include "device_callouts.hpp"
1718c42b0fSMatt Spinler 
1818c42b0fSMatt Spinler #include "paths.hpp"
1918c42b0fSMatt Spinler 
2018c42b0fSMatt Spinler #include <fstream>
2118c42b0fSMatt Spinler #include <phosphor-logging/log.hpp>
2218c42b0fSMatt Spinler #include <regex>
2318c42b0fSMatt Spinler 
2418c42b0fSMatt Spinler namespace openpower::pels::device_callouts
2518c42b0fSMatt Spinler {
2618c42b0fSMatt Spinler 
2718c42b0fSMatt Spinler constexpr auto debugFilePath = "/etc/phosphor-logging/";
2818c42b0fSMatt Spinler constexpr auto calloutFileSuffix = "_dev_callouts.json";
2918c42b0fSMatt Spinler 
3018c42b0fSMatt Spinler namespace fs = std::filesystem;
3118c42b0fSMatt Spinler using namespace phosphor::logging;
3218c42b0fSMatt Spinler 
3318c42b0fSMatt Spinler namespace util
3418c42b0fSMatt Spinler {
3518c42b0fSMatt Spinler 
3618c42b0fSMatt Spinler fs::path getJSONFilename(const std::vector<std::string>& compatibleList)
3718c42b0fSMatt Spinler {
3818c42b0fSMatt Spinler     auto basePath = getPELReadOnlyDataPath();
3918c42b0fSMatt Spinler     fs::path fullPath;
4018c42b0fSMatt Spinler 
4118c42b0fSMatt Spinler     // Find an entry in the list of compatible system names that
4218c42b0fSMatt Spinler     // matches a filename we have.
4318c42b0fSMatt Spinler 
4418c42b0fSMatt Spinler     for (const auto& name : compatibleList)
4518c42b0fSMatt Spinler     {
4618c42b0fSMatt Spinler         fs::path filename = name + calloutFileSuffix;
4718c42b0fSMatt Spinler 
4818c42b0fSMatt Spinler         // Check the debug path first
4918c42b0fSMatt Spinler         fs::path path{fs::path{debugFilePath} / filename};
5018c42b0fSMatt Spinler 
5118c42b0fSMatt Spinler         if (fs::exists(path))
5218c42b0fSMatt Spinler         {
5318c42b0fSMatt Spinler             log<level::INFO>("Found device callout debug file");
5418c42b0fSMatt Spinler             fullPath = path;
5518c42b0fSMatt Spinler             break;
5618c42b0fSMatt Spinler         }
5718c42b0fSMatt Spinler 
5818c42b0fSMatt Spinler         path = basePath / filename;
5918c42b0fSMatt Spinler 
6018c42b0fSMatt Spinler         if (fs::exists(path))
6118c42b0fSMatt Spinler         {
6218c42b0fSMatt Spinler             fullPath = path;
6318c42b0fSMatt Spinler             break;
6418c42b0fSMatt Spinler         }
6518c42b0fSMatt Spinler     }
6618c42b0fSMatt Spinler 
6718c42b0fSMatt Spinler     if (fullPath.empty())
6818c42b0fSMatt Spinler     {
6918c42b0fSMatt Spinler         throw std::invalid_argument(
7018c42b0fSMatt Spinler             "No JSON dev path callout file for this system");
7118c42b0fSMatt Spinler     }
7218c42b0fSMatt Spinler 
7318c42b0fSMatt Spinler     return fullPath;
7418c42b0fSMatt Spinler }
7518c42b0fSMatt Spinler 
7618c42b0fSMatt Spinler /**
7718c42b0fSMatt Spinler  * @brief Reads the callout JSON into an object based on the
7818c42b0fSMatt Spinler  *        compatible system names list.
7918c42b0fSMatt Spinler  *
8018c42b0fSMatt Spinler  * @param[in] compatibleList - The list of compatible names for this
8118c42b0fSMatt Spinler  *                             system.
8218c42b0fSMatt Spinler  *
8318c42b0fSMatt Spinler  * @return nlohmann::json - The JSON object
8418c42b0fSMatt Spinler  */
8518c42b0fSMatt Spinler nlohmann::json loadJSON(const std::vector<std::string>& compatibleList)
8618c42b0fSMatt Spinler {
8718c42b0fSMatt Spinler     auto filename = getJSONFilename(compatibleList);
8818c42b0fSMatt Spinler     std::ifstream file{filename};
8918c42b0fSMatt Spinler     return nlohmann::json::parse(file);
9018c42b0fSMatt Spinler }
9118c42b0fSMatt Spinler 
9218c42b0fSMatt Spinler std::vector<device_callouts::Callout>
9318c42b0fSMatt Spinler     calloutI2C(size_t i2cBus, uint8_t i2cAddress,
9418c42b0fSMatt Spinler                const nlohmann::json& calloutJSON)
9518c42b0fSMatt Spinler {
9618c42b0fSMatt Spinler     // TODO
9718c42b0fSMatt Spinler     return {};
9818c42b0fSMatt Spinler }
9918c42b0fSMatt Spinler 
10018c42b0fSMatt Spinler std::vector<device_callouts::Callout> findCallouts(const std::string& devPath,
10118c42b0fSMatt Spinler                                                    const nlohmann::json& json)
10218c42b0fSMatt Spinler {
10318c42b0fSMatt Spinler     std::vector<Callout> callouts;
104*a307089cSMatt Spinler     fs::path path;
10518c42b0fSMatt Spinler 
106*a307089cSMatt Spinler     // Gives the /sys/devices/platform/ path
107*a307089cSMatt Spinler     try
108*a307089cSMatt Spinler     {
109*a307089cSMatt Spinler         path = fs::canonical(devPath);
110*a307089cSMatt Spinler     }
111*a307089cSMatt Spinler     catch (const fs::filesystem_error& e)
112*a307089cSMatt Spinler     {
113*a307089cSMatt Spinler         // Path not there, still try to do the callout
114*a307089cSMatt Spinler         path = devPath;
115*a307089cSMatt Spinler     }
116*a307089cSMatt Spinler 
117*a307089cSMatt Spinler     switch (util::getCalloutType(path))
118*a307089cSMatt Spinler     {
119*a307089cSMatt Spinler         case util::CalloutType::i2c:
120*a307089cSMatt Spinler             // callouts = calloutI2CUsingPath(errnoValue, path, json);
121*a307089cSMatt Spinler             break;
122*a307089cSMatt Spinler         case util::CalloutType::fsi:
123*a307089cSMatt Spinler             // callouts = calloutFSI(errnoValue, path, json);
124*a307089cSMatt Spinler             break;
125*a307089cSMatt Spinler         case util::CalloutType::fsii2c:
126*a307089cSMatt Spinler             // callouts = calloutFSII2C(errnoValue, path, json);
127*a307089cSMatt Spinler             break;
128*a307089cSMatt Spinler         case util::CalloutType::fsispi:
129*a307089cSMatt Spinler             // callouts = calloutFSISPI(errnoValue, path, json);
130*a307089cSMatt Spinler             break;
131*a307089cSMatt Spinler         default:
132*a307089cSMatt Spinler             std::string msg =
133*a307089cSMatt Spinler                 "Could not get callout type from device path: " + path.string();
134*a307089cSMatt Spinler             throw std::invalid_argument{msg.c_str()};
135*a307089cSMatt Spinler             break;
136*a307089cSMatt Spinler     }
13718c42b0fSMatt Spinler 
13818c42b0fSMatt Spinler     return callouts;
13918c42b0fSMatt Spinler }
14018c42b0fSMatt Spinler 
141*a307089cSMatt Spinler CalloutType getCalloutType(const std::string& devPath)
142*a307089cSMatt Spinler {
143*a307089cSMatt Spinler     if ((devPath.find("fsi-master") != std::string::npos) &&
144*a307089cSMatt Spinler         (devPath.find("i2c-") != std::string::npos))
145*a307089cSMatt Spinler     {
146*a307089cSMatt Spinler         return CalloutType::fsii2c;
147*a307089cSMatt Spinler     }
148*a307089cSMatt Spinler 
149*a307089cSMatt Spinler     if ((devPath.find("fsi-master") != std::string::npos) &&
150*a307089cSMatt Spinler         (devPath.find("spi") != std::string::npos))
151*a307089cSMatt Spinler     {
152*a307089cSMatt Spinler         return CalloutType::fsispi;
153*a307089cSMatt Spinler     }
154*a307089cSMatt Spinler 
155*a307089cSMatt Spinler     // Treat anything else FSI related as plain FSI
156*a307089cSMatt Spinler     if (devPath.find("fsi-master") != std::string::npos)
157*a307089cSMatt Spinler     {
158*a307089cSMatt Spinler         return CalloutType::fsi;
159*a307089cSMatt Spinler     }
160*a307089cSMatt Spinler 
161*a307089cSMatt Spinler     if (devPath.find("i2c-bus/i2c-") != std::string::npos)
162*a307089cSMatt Spinler     {
163*a307089cSMatt Spinler         return CalloutType::i2c;
164*a307089cSMatt Spinler     }
165*a307089cSMatt Spinler 
166*a307089cSMatt Spinler     return CalloutType::unknown;
167*a307089cSMatt Spinler }
168*a307089cSMatt Spinler 
16918c42b0fSMatt Spinler } // namespace util
17018c42b0fSMatt Spinler 
17118c42b0fSMatt Spinler std::vector<Callout> getCallouts(const std::string& devPath,
17218c42b0fSMatt Spinler                                  const std::vector<std::string>& compatibleList)
17318c42b0fSMatt Spinler {
17418c42b0fSMatt Spinler     auto json = util::loadJSON(compatibleList);
17518c42b0fSMatt Spinler     return util::findCallouts(devPath, json);
17618c42b0fSMatt Spinler }
17718c42b0fSMatt Spinler 
17818c42b0fSMatt Spinler std::vector<Callout>
17918c42b0fSMatt Spinler     getI2CCallouts(size_t i2cBus, uint8_t i2cAddress,
18018c42b0fSMatt Spinler                    const std::vector<std::string>& compatibleList)
18118c42b0fSMatt Spinler {
18218c42b0fSMatt Spinler     auto json = util::loadJSON(compatibleList);
18318c42b0fSMatt Spinler     return util::calloutI2C(i2cBus, i2cAddress, json);
18418c42b0fSMatt Spinler }
18518c42b0fSMatt Spinler 
18618c42b0fSMatt Spinler } // namespace openpower::pels::device_callouts
187