1 #pragma once
2 
3 #include "lpcsnoop/snoop.hpp"
4 
5 #include <boost/asio.hpp>
6 #include <gpiod.hpp>
7 #include <sdbusplus/asio/connection.hpp>
8 #include <sdbusplus/asio/object_server.hpp>
9 #include <sdbusplus/asio/property.hpp>
10 #include <sdbusplus/bus.hpp>
11 #include <sdbusplus/server.hpp>
12 #include <xyz/openbmc_project/Chassis/Buttons/HostSelector/server.hpp>
13 #include <xyz/openbmc_project/State/Boot/Raw/server.hpp>
14 
15 #include <filesystem>
16 #include <iostream>
17 #include <span>
18 
19 const std::string ipmiSnoopObject = "/xyz/openbmc_project/state/boot/raw";
20 
21 const int hostParseIdx = 3;
22 const int maxPostcode = 255;
23 const int maxPosition = 4;
24 
25 extern bool sevenSegmentLedEnabled;
26 
27 extern std::vector<gpiod::line> led_lines;
28 
29 using Selector =
30     sdbusplus::xyz::openbmc_project::Chassis::Buttons::server::HostSelector;
31 
32 const std::string selectorService = "xyz.openbmc_project.Chassis.Buttons";
33 const std::string selectorObject =
34     "/xyz/openbmc_project/Chassis/Buttons/HostSelector";
35 const std::string selectorIface =
36     "xyz.openbmc_project.Chassis.Buttons.HostSelector";
37 
38 const std::string rawObject = "/xyz/openbmc_project/state/boot";
39 const std::string rawIface = "xyz.openbmc_project.State.Boot.Raw";
40 const std::string rawService = "xyz.openbmc_project.State.Boot.Raw";
41 
42 int postCodeIpmiHandler(const std::string& snoopObject,
43                         const std::string& snoopDbus, sdbusplus::bus_t& bus,
44                         std::span<std::string> host);
45 
46 uint32_t getSelectorPosition(sdbusplus::bus_t& bus);
47 
48 struct IpmiPostReporter : PostObject
49 {
50     IpmiPostReporter(sdbusplus::bus_t& bus, const char* objPath) :
51         PostObject(bus, objPath), bus(bus),
52         propertiesChangedSignalRaw(
53             bus,
54             sdbusplus::bus::match::rules::propertiesChanged(objPath, rawIface),
55 
56             [this, &bus](sdbusplus::message_t& msg) {
57         using primarycode_t = uint64_t;
58         using secondarycode_t = std::vector<uint8_t>;
59         using postcode_t = std::tuple<primarycode_t, secondarycode_t>;
60 
61         /* sevenSegmentLedEnabled flag is set when GPIO pins are not
62         there 7 seg display for fewer platforms. So, the code for
63         postcode dispay and Get Selector position can be skipped in
64         those platforms.
65         */
66         if (!sevenSegmentLedEnabled)
67         {
68             return;
69         }
70 
71         std::string objectName;
72         std::string InterfaceName;
73         std::map<std::string, std::variant<postcode_t>> msgData;
74         msg.read(InterfaceName, msgData);
75 
76         std::filesystem::path name(msg.get_path());
77         objectName = name.filename();
78 
79         std::string hostNumStr = objectName.substr(hostParseIdx);
80         size_t hostNum = std::stoi(hostNumStr);
81 
82         size_t position = getSelectorPosition(bus);
83 
84         if (position > maxPosition)
85         {
86             std::cerr << "Invalid position. Position should be 1 to 4 "
87                          "for all hosts "
88                       << std::endl;
89         }
90 
91         // Check if it was the Value property that changed.
92         auto valPropMap = msgData.find("Value");
93         if (valPropMap == msgData.end())
94         {
95             std::cerr << "Value property is not found " << std::endl;
96             return;
97         }
98         uint64_t postcode =
99             std::get<0>(std::get<postcode_t>(valPropMap->second));
100 
101         if (postcode <= maxPostcode)
102         {
103             if (position == hostNum)
104             {
105                 uint8_t postcode_8bit =
106                     static_cast<uint8_t>(postcode & 0x0000FF);
107 
108                 // write postcode into seven segment display
109                 if (postCodeDisplay(postcode_8bit) < 0)
110                 {
111                     fprintf(stderr, "Error in display the postcode\n");
112                 }
113             }
114             else
115             {
116                 fprintf(stderr, "Host Selector Position and host "
117                                 "number is not matched..\n");
118             }
119         }
120         else
121         {
122             fprintf(stderr, "invalid postcode value \n");
123         }
124     })
125     {}
126 
127     sdbusplus::bus_t& bus;
128     sdbusplus::bus::match_t propertiesChangedSignalRaw;
129     int postCodeDisplay(uint8_t);
130     void getSelectorPositionSignal(sdbusplus::bus_t& bus);
131 };
132