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 
17*e881852bSJames Feist #include <systemd/sd-journal.h>
18*e881852bSJames 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>
26c95cf671SFeist, James #include <string>
27c95cf671SFeist, James #include <variant>
28c95cf671SFeist, James #include <vector>
29c95cf671SFeist, James 
30c95cf671SFeist, James using GetSubTreeType = std::vector<
31c95cf671SFeist, James     std::pair<std::string,
32c95cf671SFeist, James               std::vector<std::pair<std::string, std::vector<std::string>>>>>;
33c95cf671SFeist, James using BasicVariantType =
34c95cf671SFeist, James     std::variant<std::vector<std::string>, std::string, int64_t, uint64_t,
35c95cf671SFeist, James                  double, int32_t, uint32_t, int16_t, uint16_t, uint8_t, bool>;
360b236ab8SJames Feist using Association = std::tuple<std::string, std::string, std::string>;
37c95cf671SFeist, James 
38c95cf671SFeist, James namespace mapper
39c95cf671SFeist, James {
40c95cf671SFeist, James constexpr const char* busName = "xyz.openbmc_project.ObjectMapper";
41c95cf671SFeist, James constexpr const char* path = "/xyz/openbmc_project/object_mapper";
42c95cf671SFeist, James constexpr const char* interface = "xyz.openbmc_project.ObjectMapper";
43c95cf671SFeist, James constexpr const char* subtree = "GetSubTree";
44c95cf671SFeist, James } // namespace mapper
45c95cf671SFeist, James 
46c95cf671SFeist, James namespace entityManager
47c95cf671SFeist, James {
48c95cf671SFeist, James constexpr const char* busName = "xyz.openbmc_project.EntityManager";
49c95cf671SFeist, James } // namespace entityManager
50c95cf671SFeist, James 
51c95cf671SFeist, James namespace inventory
52c95cf671SFeist, James {
53c95cf671SFeist, James constexpr const char* interface = "xyz.openbmc_project.Inventory.Item";
54c95cf671SFeist, James } // namespace inventory
55c95cf671SFeist, James 
5609dd2314SJames Feist namespace ledGroup
5709dd2314SJames Feist {
5809dd2314SJames Feist constexpr const char* interface = "xyz.openbmc_project.Led.Group";
5909dd2314SJames Feist constexpr const char* asserted = "Asserted";
6009dd2314SJames Feist } // namespace ledGroup
6109dd2314SJames Feist 
629f6565dbSJames Feist namespace properties
639f6565dbSJames Feist {
649f6565dbSJames Feist constexpr const char* interface = "org.freedesktop.DBus.Properties";
659f6565dbSJames Feist constexpr const char* get = "Get";
669f6565dbSJames Feist } // namespace properties
679f6565dbSJames Feist 
689f6565dbSJames Feist namespace power
699f6565dbSJames Feist {
709f6565dbSJames Feist const static constexpr char* busname = "xyz.openbmc_project.State.Host";
719f6565dbSJames Feist const static constexpr char* interface = "xyz.openbmc_project.State.Host";
729f6565dbSJames Feist const static constexpr char* path = "/xyz/openbmc_project/state/host0";
739f6565dbSJames Feist const static constexpr char* property = "CurrentHostState";
749f6565dbSJames Feist } // namespace power
759f6565dbSJames Feist 
7642b49c17SJames Feist namespace association
7742b49c17SJames Feist {
7842b49c17SJames Feist const static constexpr char* interface =
7942b49c17SJames Feist     "xyz.openbmc_project.Association.Definitions";
8042b49c17SJames Feist } // namespace association
8142b49c17SJames Feist 
82c95cf671SFeist, James namespace hsbp
83c95cf671SFeist, James {
84c95cf671SFeist, James enum class registers : uint8_t
85c95cf671SFeist, James {
86c95cf671SFeist, James     fpgaIdH = 0x0,
87c95cf671SFeist, James     fpgaIdL = 0x1,
88c95cf671SFeist, James     typeId = 0x2,
89c95cf671SFeist, James     bootVer = 0x3,
90c95cf671SFeist, James     fpgaVer = 0x4,
91c95cf671SFeist, James     securityRev = 0x5,
92c95cf671SFeist, James     funSupported = 0x6,
93c95cf671SFeist, James     numDisks = 0x7,
94c95cf671SFeist, James     presence = 0x8,
95c95cf671SFeist, James     ssdIFDET = 0x9,
96c95cf671SFeist, James     ifdetPart = 0xA,
97c95cf671SFeist, James     statusLocate = 0xB,
98c95cf671SFeist, James     statusFail = 0xC,
99c95cf671SFeist, James     statusRebuild = 0xD,
100c95cf671SFeist, James     ledOverride = 0xE,
101c95cf671SFeist, James     ledStatus = 0xF,
102c95cf671SFeist, James     ledPattern0 = 0x10,
103c95cf671SFeist, James     ledPattern1 = 0x11,
104c95cf671SFeist, James     ledPattern2 = 0x12,
105c95cf671SFeist, James     ledPattern3 = 0x13,
106c95cf671SFeist, James     ledPattern4 = 0x14,
107c95cf671SFeist, James     ledPattern5 = 0x15,
108c95cf671SFeist, James     ledPattern6 = 0x16,
109c95cf671SFeist, James     ledPattern7 = 0x17,
110c95cf671SFeist, James };
111c95cf671SFeist, James 
112c95cf671SFeist, James } // namespace hsbp
1139f6565dbSJames Feist 
1149f6565dbSJames Feist static std::unique_ptr<sdbusplus::bus::match::match> powerMatch = nullptr;
1159f6565dbSJames Feist static bool powerStatusOn = false;
1169f6565dbSJames Feist 
1179f6565dbSJames Feist bool isPowerOn(void)
1189f6565dbSJames Feist {
1199f6565dbSJames Feist     if (!powerMatch)
1209f6565dbSJames Feist     {
1219f6565dbSJames Feist         throw std::runtime_error("Power Match Not Created");
1229f6565dbSJames Feist     }
1239f6565dbSJames Feist     return powerStatusOn;
1249f6565dbSJames Feist }
1259f6565dbSJames Feist 
1269f6565dbSJames Feist void setupPowerMatch(const std::shared_ptr<sdbusplus::asio::connection>& conn)
1279f6565dbSJames Feist {
1289f6565dbSJames Feist     static boost::asio::steady_timer timer(conn->get_io_context());
1299f6565dbSJames Feist     // create a match for powergood changes, first time do a method call to
1309f6565dbSJames Feist     // cache the correct value
1319f6565dbSJames Feist     if (powerMatch)
1329f6565dbSJames Feist     {
1339f6565dbSJames Feist         return;
1349f6565dbSJames Feist     }
1359f6565dbSJames Feist 
1369f6565dbSJames Feist     powerMatch = std::make_unique<sdbusplus::bus::match::match>(
1379f6565dbSJames Feist         static_cast<sdbusplus::bus::bus&>(*conn),
1389f6565dbSJames Feist         "type='signal',interface='" + std::string(properties::interface) +
1399f6565dbSJames Feist             "',path='" + std::string(power::path) + "',arg0='" +
1409f6565dbSJames Feist             std::string(power::interface) + "'",
1419f6565dbSJames Feist         [](sdbusplus::message::message& message) {
1429f6565dbSJames Feist             std::string objectName;
1439f6565dbSJames Feist             boost::container::flat_map<std::string, std::variant<std::string>>
1449f6565dbSJames Feist                 values;
1459f6565dbSJames Feist             message.read(objectName, values);
1469f6565dbSJames Feist             auto findState = values.find(power::property);
1479f6565dbSJames Feist             if (findState != values.end())
1489f6565dbSJames Feist             {
1499f6565dbSJames Feist                 bool on = boost::ends_with(
1509f6565dbSJames Feist                     std::get<std::string>(findState->second), "Running");
1519f6565dbSJames Feist                 if (!on)
1529f6565dbSJames Feist                 {
1539f6565dbSJames Feist                     timer.cancel();
1549f6565dbSJames Feist                     powerStatusOn = false;
1559f6565dbSJames Feist                     return;
1569f6565dbSJames Feist                 }
1579f6565dbSJames Feist                 // on comes too quickly
1589f6565dbSJames Feist                 timer.expires_after(std::chrono::seconds(10));
1599f6565dbSJames Feist                 timer.async_wait([](boost::system::error_code ec) {
1609f6565dbSJames Feist                     if (ec == boost::asio::error::operation_aborted)
1619f6565dbSJames Feist                     {
1629f6565dbSJames Feist                         return;
1639f6565dbSJames Feist                     }
1649f6565dbSJames Feist                     else if (ec)
1659f6565dbSJames Feist                     {
1669f6565dbSJames Feist                         std::cerr << "Timer error " << ec.message() << "\n";
1679f6565dbSJames Feist                         return;
1689f6565dbSJames Feist                     }
1699f6565dbSJames Feist                     powerStatusOn = true;
1709f6565dbSJames Feist                 });
1719f6565dbSJames Feist             }
1729f6565dbSJames Feist         });
1739f6565dbSJames Feist 
1749f6565dbSJames Feist     conn->async_method_call(
1759f6565dbSJames Feist         [](boost::system::error_code ec,
1769f6565dbSJames Feist            const std::variant<std::string>& state) {
1779f6565dbSJames Feist             if (ec)
1789f6565dbSJames Feist             {
1799f6565dbSJames Feist                 // we commonly come up before power control, we'll capture the
1809f6565dbSJames Feist                 // property change later
1819f6565dbSJames Feist                 return;
1829f6565dbSJames Feist             }
1839f6565dbSJames Feist             powerStatusOn =
1849f6565dbSJames Feist                 boost::ends_with(std::get<std::string>(state), "Running");
1859f6565dbSJames Feist         },
1869f6565dbSJames Feist         power::busname, power::path, properties::interface, properties::get,
1879f6565dbSJames Feist         power::interface, power::property);
1889f6565dbSJames Feist }
189*e881852bSJames Feist 
190*e881852bSJames Feist inline void logDeviceAdded(const std::string& model, const std::string& type,
191*e881852bSJames Feist                            const std::string& sn)
192*e881852bSJames Feist {
193*e881852bSJames Feist     sd_journal_send("MESSAGE=%s", "Inventory Added", "PRIORITY=%i", LOG_ERR,
194*e881852bSJames Feist                     "REDFISH_MESSAGE_ID=%s", "OpenBMC.0.1.InventoryAdded",
195*e881852bSJames Feist                     "REDFISH_MESSAGE_ARGS=%s,%s,%s", model.c_str(),
196*e881852bSJames Feist                     type.c_str(), sn.c_str(), NULL);
197*e881852bSJames Feist }
198*e881852bSJames Feist 
199*e881852bSJames Feist inline void logDeviceRemoved(const std::string& model, const std::string& type,
200*e881852bSJames Feist                              const std::string& sn)
201*e881852bSJames Feist {
202*e881852bSJames Feist     sd_journal_send("MESSAGE=%s", "Inventory Removed", "PRIORITY=%i", LOG_ERR,
203*e881852bSJames Feist                     "REDFISH_MESSAGE_ID=%s", "OpenBMC.0.1.InventoryRemoved",
204*e881852bSJames Feist                     "REDFISH_MESSAGE_ARGS=%s,%s,%s", model.c_str(),
205*e881852bSJames Feist                     type.c_str(), sn.c_str(), NULL);
206*e881852bSJames Feist }
207*e881852bSJames Feist 
208*e881852bSJames Feist inline void logDriveError(const std::string& name)
209*e881852bSJames Feist {
210*e881852bSJames Feist     sd_journal_send("MESSAGE=%s", "Drive Error", "PRIORITY=%i", LOG_ERR,
211*e881852bSJames Feist                     "REDFISH_MESSAGE_ID=%s", "OpenBMC.0.1.DriveError",
212*e881852bSJames Feist                     "REDFISH_MESSAGE_ARGS=%s", name.c_str(), NULL);
213*e881852bSJames Feist }
214