1c95cf671SFeist, James /*
2c95cf671SFeist, James // Copyright (c) 2019 Intel Corporation
3c95cf671SFeist, James //
4c95cf671SFeist, James // Licensed under the Apache License, Version 2.0 (the "License");
5c95cf671SFeist, James // you may not use this file except in compliance with the License.
6c95cf671SFeist, James // You may obtain a copy of the License at
7c95cf671SFeist, James //
8c95cf671SFeist, James //      http://www.apache.org/licenses/LICENSE-2.0
9c95cf671SFeist, James //
10c95cf671SFeist, James // Unless required by applicable law or agreed to in writing, software
11c95cf671SFeist, James // distributed under the License is distributed on an "AS IS" BASIS,
12c95cf671SFeist, James // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c95cf671SFeist, James // See the License for the specific language governing permissions and
14c95cf671SFeist, James // limitations under the License.
15c95cf671SFeist, James */
16c95cf671SFeist, James 
17e881852bSJames Feist #include <systemd/sd-journal.h>
18e881852bSJames Feist 
199f6565dbSJames Feist #include <boost/algorithm/string/predicate.hpp>
209f6565dbSJames Feist #include <boost/asio/io_context.hpp>
219f6565dbSJames Feist #include <boost/asio/steady_timer.hpp>
229f6565dbSJames Feist #include <boost/container/flat_map.hpp>
23c95cf671SFeist, James #include <cstdint>
249f6565dbSJames Feist #include <iostream>
259f6565dbSJames Feist #include <sdbusplus/asio/connection.hpp>
26*ff1c36e5SPatrick Williams #include <sdbusplus/bus.hpp>
2726067f6aSJonathan Doman #include <sdbusplus/bus/match.hpp>
28c95cf671SFeist, James #include <string>
29c95cf671SFeist, James #include <variant>
30c95cf671SFeist, James #include <vector>
31c95cf671SFeist, James 
32c95cf671SFeist, James using GetSubTreeType = std::vector<
33c95cf671SFeist, James     std::pair<std::string,
34c95cf671SFeist, James               std::vector<std::pair<std::string, std::vector<std::string>>>>>;
35c95cf671SFeist, James using BasicVariantType =
36c95cf671SFeist, James     std::variant<std::vector<std::string>, std::string, int64_t, uint64_t,
37c95cf671SFeist, James                  double, int32_t, uint32_t, int16_t, uint16_t, uint8_t, bool>;
380b236ab8SJames Feist using Association = std::tuple<std::string, std::string, std::string>;
39c95cf671SFeist, James 
40d0d36f10SJames Feist constexpr const char* assetTag =
41d0d36f10SJames Feist     "xyz.openbmc_project.Inventory.Decorator.Asset";
42d0d36f10SJames Feist 
43c95cf671SFeist, James namespace mapper
44c95cf671SFeist, James {
45c95cf671SFeist, James constexpr const char* busName = "xyz.openbmc_project.ObjectMapper";
46c95cf671SFeist, James constexpr const char* path = "/xyz/openbmc_project/object_mapper";
47c95cf671SFeist, James constexpr const char* interface = "xyz.openbmc_project.ObjectMapper";
48c95cf671SFeist, James constexpr const char* subtree = "GetSubTree";
49c95cf671SFeist, James } // namespace mapper
50c95cf671SFeist, James 
51c95cf671SFeist, James namespace entityManager
52c95cf671SFeist, James {
53c95cf671SFeist, James constexpr const char* busName = "xyz.openbmc_project.EntityManager";
54c95cf671SFeist, James } // namespace entityManager
55c95cf671SFeist, James 
56c95cf671SFeist, James namespace inventory
57c95cf671SFeist, James {
58c95cf671SFeist, James constexpr const char* interface = "xyz.openbmc_project.Inventory.Item";
59c95cf671SFeist, James } // namespace inventory
60c95cf671SFeist, James 
6109dd2314SJames Feist namespace ledGroup
6209dd2314SJames Feist {
6309dd2314SJames Feist constexpr const char* interface = "xyz.openbmc_project.Led.Group";
6409dd2314SJames Feist constexpr const char* asserted = "Asserted";
6509dd2314SJames Feist } // namespace ledGroup
6609dd2314SJames Feist 
679f6565dbSJames Feist namespace properties
689f6565dbSJames Feist {
699f6565dbSJames Feist constexpr const char* interface = "org.freedesktop.DBus.Properties";
709f6565dbSJames Feist constexpr const char* get = "Get";
719f6565dbSJames Feist } // namespace properties
729f6565dbSJames Feist 
739f6565dbSJames Feist namespace power
749f6565dbSJames Feist {
759f6565dbSJames Feist const static constexpr char* busname = "xyz.openbmc_project.State.Host";
769f6565dbSJames Feist const static constexpr char* interface = "xyz.openbmc_project.State.Host";
779f6565dbSJames Feist const static constexpr char* path = "/xyz/openbmc_project/state/host0";
789f6565dbSJames Feist const static constexpr char* property = "CurrentHostState";
799f6565dbSJames Feist } // namespace power
809f6565dbSJames Feist 
8142b49c17SJames Feist namespace association
8242b49c17SJames Feist {
8342b49c17SJames Feist const static constexpr char* interface =
8442b49c17SJames Feist     "xyz.openbmc_project.Association.Definitions";
8542b49c17SJames Feist } // namespace association
8642b49c17SJames Feist 
87c95cf671SFeist, James namespace hsbp
88c95cf671SFeist, James {
89c95cf671SFeist, James enum class registers : uint8_t
90c95cf671SFeist, James {
91c95cf671SFeist, James     fpgaIdH = 0x0,
92c95cf671SFeist, James     fpgaIdL = 0x1,
93c95cf671SFeist, James     typeId = 0x2,
94c95cf671SFeist, James     bootVer = 0x3,
95c95cf671SFeist, James     fpgaVer = 0x4,
96c95cf671SFeist, James     securityRev = 0x5,
97c95cf671SFeist, James     funSupported = 0x6,
98c95cf671SFeist, James     numDisks = 0x7,
99c95cf671SFeist, James     presence = 0x8,
100c95cf671SFeist, James     ssdIFDET = 0x9,
101c95cf671SFeist, James     ifdetPart = 0xA,
102c95cf671SFeist, James     statusLocate = 0xB,
103c95cf671SFeist, James     statusFail = 0xC,
104c95cf671SFeist, James     statusRebuild = 0xD,
105c95cf671SFeist, James     ledOverride = 0xE,
106c95cf671SFeist, James     ledStatus = 0xF,
107c95cf671SFeist, James     ledPattern0 = 0x10,
108c95cf671SFeist, James     ledPattern1 = 0x11,
109c95cf671SFeist, James     ledPattern2 = 0x12,
110c95cf671SFeist, James     ledPattern3 = 0x13,
111c95cf671SFeist, James     ledPattern4 = 0x14,
112c95cf671SFeist, James     ledPattern5 = 0x15,
113c95cf671SFeist, James     ledPattern6 = 0x16,
114c95cf671SFeist, James     ledPattern7 = 0x17,
115c95cf671SFeist, James };
116c95cf671SFeist, James 
117c95cf671SFeist, James } // namespace hsbp
1189f6565dbSJames Feist 
11926067f6aSJonathan Doman static std::unique_ptr<sdbusplus::bus::match_t> powerMatch = nullptr;
1209f6565dbSJames Feist static bool powerStatusOn = false;
1219f6565dbSJames Feist 
isPowerOn(void)1229f6565dbSJames Feist bool isPowerOn(void)
1239f6565dbSJames Feist {
1249f6565dbSJames Feist     if (!powerMatch)
1259f6565dbSJames Feist     {
1269f6565dbSJames Feist         throw std::runtime_error("Power Match Not Created");
1279f6565dbSJames Feist     }
1289f6565dbSJames Feist     return powerStatusOn;
1299f6565dbSJames Feist }
1309f6565dbSJames Feist 
setupPowerMatch(const std::shared_ptr<sdbusplus::asio::connection> & conn)1319f6565dbSJames Feist void setupPowerMatch(const std::shared_ptr<sdbusplus::asio::connection>& conn)
1329f6565dbSJames Feist {
1339f6565dbSJames Feist     static boost::asio::steady_timer timer(conn->get_io_context());
1349f6565dbSJames Feist     // create a match for powergood changes, first time do a method call to
1359f6565dbSJames Feist     // cache the correct value
1369f6565dbSJames Feist     if (powerMatch)
1379f6565dbSJames Feist     {
1389f6565dbSJames Feist         return;
1399f6565dbSJames Feist     }
1409f6565dbSJames Feist 
14126067f6aSJonathan Doman     powerMatch = std::make_unique<sdbusplus::bus::match_t>(
142*ff1c36e5SPatrick Williams         static_cast<sdbusplus::bus_t&>(*conn),
1439f6565dbSJames Feist         "type='signal',interface='" + std::string(properties::interface) +
1449f6565dbSJames Feist             "',path='" + std::string(power::path) + "',arg0='" +
1459f6565dbSJames Feist             std::string(power::interface) + "'",
146*ff1c36e5SPatrick Williams         [](sdbusplus::message_t& message) {
1479f6565dbSJames Feist             std::string objectName;
1489f6565dbSJames Feist             boost::container::flat_map<std::string, std::variant<std::string>>
1499f6565dbSJames Feist                 values;
1509f6565dbSJames Feist             message.read(objectName, values);
1519f6565dbSJames Feist             auto findState = values.find(power::property);
1529f6565dbSJames Feist             if (findState != values.end())
1539f6565dbSJames Feist             {
1549f6565dbSJames Feist                 bool on = boost::ends_with(
1559f6565dbSJames Feist                     std::get<std::string>(findState->second), "Running");
1569f6565dbSJames Feist                 if (!on)
1579f6565dbSJames Feist                 {
1589f6565dbSJames Feist                     timer.cancel();
1599f6565dbSJames Feist                     powerStatusOn = false;
1609f6565dbSJames Feist                     return;
1619f6565dbSJames Feist                 }
1629f6565dbSJames Feist                 // on comes too quickly
1639f6565dbSJames Feist                 timer.expires_after(std::chrono::seconds(10));
1649f6565dbSJames Feist                 timer.async_wait([](boost::system::error_code ec) {
1659f6565dbSJames Feist                     if (ec == boost::asio::error::operation_aborted)
1669f6565dbSJames Feist                     {
1679f6565dbSJames Feist                         return;
1689f6565dbSJames Feist                     }
1699f6565dbSJames Feist                     else if (ec)
1709f6565dbSJames Feist                     {
1719f6565dbSJames Feist                         std::cerr << "Timer error " << ec.message() << "\n";
1729f6565dbSJames Feist                         return;
1739f6565dbSJames Feist                     }
1749f6565dbSJames Feist                     powerStatusOn = true;
1759f6565dbSJames Feist                 });
1769f6565dbSJames Feist             }
1779f6565dbSJames Feist         });
1789f6565dbSJames Feist 
1799f6565dbSJames Feist     conn->async_method_call(
1809f6565dbSJames Feist         [](boost::system::error_code ec,
1819f6565dbSJames Feist            const std::variant<std::string>& state) {
1829f6565dbSJames Feist             if (ec)
1839f6565dbSJames Feist             {
1849f6565dbSJames Feist                 // we commonly come up before power control, we'll capture the
1859f6565dbSJames Feist                 // property change later
1869f6565dbSJames Feist                 return;
1879f6565dbSJames Feist             }
1889f6565dbSJames Feist             powerStatusOn =
1899f6565dbSJames Feist                 boost::ends_with(std::get<std::string>(state), "Running");
1909f6565dbSJames Feist         },
1919f6565dbSJames Feist         power::busname, power::path, properties::interface, properties::get,
1929f6565dbSJames Feist         power::interface, power::property);
1939f6565dbSJames Feist }
194e881852bSJames Feist 
logDeviceAdded(const std::string & model,const std::string & type,const std::string & sn)195e881852bSJames Feist inline void logDeviceAdded(const std::string& model, const std::string& type,
196e881852bSJames Feist                            const std::string& sn)
197e881852bSJames Feist {
198e881852bSJames Feist     sd_journal_send("MESSAGE=%s", "Inventory Added", "PRIORITY=%i", LOG_ERR,
199e881852bSJames Feist                     "REDFISH_MESSAGE_ID=%s", "OpenBMC.0.1.InventoryAdded",
200e881852bSJames Feist                     "REDFISH_MESSAGE_ARGS=%s,%s,%s", model.c_str(),
201e881852bSJames Feist                     type.c_str(), sn.c_str(), NULL);
202e881852bSJames Feist }
203e881852bSJames Feist 
logDeviceRemoved(const std::string & model,const std::string & type,const std::string & sn)204e881852bSJames Feist inline void logDeviceRemoved(const std::string& model, const std::string& type,
205e881852bSJames Feist                              const std::string& sn)
206e881852bSJames Feist {
207e881852bSJames Feist     sd_journal_send("MESSAGE=%s", "Inventory Removed", "PRIORITY=%i", LOG_ERR,
208e881852bSJames Feist                     "REDFISH_MESSAGE_ID=%s", "OpenBMC.0.1.InventoryRemoved",
209e881852bSJames Feist                     "REDFISH_MESSAGE_ARGS=%s,%s,%s", model.c_str(),
210e881852bSJames Feist                     type.c_str(), sn.c_str(), NULL);
211e881852bSJames Feist }
212e881852bSJames Feist 
logDriveError(const std::string & name)213e881852bSJames Feist inline void logDriveError(const std::string& name)
214e881852bSJames Feist {
215e881852bSJames Feist     sd_journal_send("MESSAGE=%s", "Drive Error", "PRIORITY=%i", LOG_ERR,
216e881852bSJames Feist                     "REDFISH_MESSAGE_ID=%s", "OpenBMC.0.1.DriveError",
217e881852bSJames Feist                     "REDFISH_MESSAGE_ARGS=%s", name.c_str(), NULL);
218e881852bSJames Feist }
219