xref: /openbmc/phosphor-host-postd/main.cpp (revision fe51495e034f506c50e828659602e46b7626482e)
133569758SPatrick Venture /**
233569758SPatrick Venture  * Copyright 2017 Google Inc.
333569758SPatrick Venture  *
433569758SPatrick Venture  * Licensed under the Apache License, Version 2.0 (the "License");
533569758SPatrick Venture  * you may not use this file except in compliance with the License.
633569758SPatrick Venture  * You may obtain a copy of the License at
733569758SPatrick Venture  *
833569758SPatrick Venture  *     http://www.apache.org/licenses/LICENSE-2.0
933569758SPatrick Venture  *
1033569758SPatrick Venture  * Unless required by applicable law or agreed to in writing, software
1133569758SPatrick Venture  * distributed under the License is distributed on an "AS IS" BASIS,
1233569758SPatrick Venture  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1333569758SPatrick Venture  * See the License for the specific language governing permissions and
1433569758SPatrick Venture  * limitations under the License.
1533569758SPatrick Venture  */
1633569758SPatrick Venture 
170269eaf3SKumar Thangavel #ifdef ENABLE_IPMI_SNOOP
180269eaf3SKumar Thangavel #include "ipmisnoop/ipmisnoop.hpp"
190269eaf3SKumar Thangavel #endif
20b5754fd4SPatrick Venture #include "lpcsnoop/snoop.hpp"
21b5754fd4SPatrick Venture 
226dac4c5eSWilliam A. Kennington III #include <endian.h>
2333569758SPatrick Venture #include <fcntl.h>
24e7b07f08SBenjamin Fair #include <getopt.h>
25b5754fd4SPatrick Venture #include <sys/epoll.h>
26b5754fd4SPatrick Venture #include <systemd/sd-event.h>
2733569758SPatrick Venture #include <unistd.h>
2833569758SPatrick Venture 
291c16ad89SKun Yi #include <sdeventplus/event.hpp>
301c16ad89SKun Yi #include <sdeventplus/source/event.hpp>
311c16ad89SKun Yi #include <sdeventplus/source/io.hpp>
326a5e0a1cSWilliam A. Kennington III #include <sdeventplus/source/signal.hpp>
3338b0946cSJonathan Doman #include <sdeventplus/source/time.hpp>
3430751ec2SWilliam A. Kennington III #include <sdeventplus/utility/sdbus.hpp>
356a5e0a1cSWilliam A. Kennington III #include <stdplus/signal.hpp>
360ea7357eSPatrick Williams 
370ea7357eSPatrick Williams #include <chrono>
380ea7357eSPatrick Williams #include <cstdint>
390ea7357eSPatrick Williams #include <exception>
400ea7357eSPatrick Williams #include <functional>
410ea7357eSPatrick Williams #include <iostream>
420ea7357eSPatrick Williams #include <optional>
4333569758SPatrick Venture #include <thread>
4433569758SPatrick Venture 
45f69ad7e6SBenjamin Fair static size_t codeSize = 1; /* Size of each POST code in bytes */
4638b0946cSJonathan Doman static bool verbose = false;
47*fe51495eSCosmo Chou static std::function<bool(std::vector<uint8_t>&, ssize_t)> procPostCode;
48e7b07f08SBenjamin Fair 
usage(const char * name)49e7b07f08SBenjamin Fair static void usage(const char* name)
50e7b07f08SBenjamin Fair {
51e7b07f08SBenjamin Fair     fprintf(stderr,
52de7a6dd7SJonathan Doman             "Usage: %s\n"
53de7a6dd7SJonathan Doman #ifdef ENABLE_IPMI_SNOOP
54de7a6dd7SJonathan Doman             "  -h, --host <host instances>  Default is '0'\n"
55de7a6dd7SJonathan Doman #else
56aade4adbSManojkiran Eda             "  -d, --device <DEVICE>  use <DEVICE> file.\n"
57fd2430d8SJonathan Doman             "  -r, --rate-limit=<N>   Only process N POST codes from the "
58fd2430d8SJonathan Doman             "device per second.\n"
59de7a6dd7SJonathan Doman             "  -b, --bytes <SIZE>     set POST code length to <SIZE> bytes. "
60de7a6dd7SJonathan Doman             "Default is 1\n"
61de7a6dd7SJonathan Doman #endif
6266efa632SWilliam A. Kennington III             "  -v, --verbose  Prints verbose information while running\n\n",
63de7a6dd7SJonathan Doman             name);
64f69ad7e6SBenjamin Fair }
65f69ad7e6SBenjamin Fair 
6638b0946cSJonathan Doman /**
6738b0946cSJonathan Doman  * Call once for each POST code received. If the number of POST codes exceeds
6838b0946cSJonathan Doman  * the configured rate limit, this function will disable the snoop device IO
6938b0946cSJonathan Doman  * source until the end of the 1 second interval, then re-enable it.
7038b0946cSJonathan Doman  *
7138b0946cSJonathan Doman  * @return Whether the rate limit is exceeded.
7238b0946cSJonathan Doman  */
rateLimit(PostReporter & reporter,sdeventplus::source::IO & ioSource)7338b0946cSJonathan Doman bool rateLimit(PostReporter& reporter, sdeventplus::source::IO& ioSource)
7438b0946cSJonathan Doman {
7538b0946cSJonathan Doman     if (reporter.rateLimit == 0)
7638b0946cSJonathan Doman     {
7738b0946cSJonathan Doman         // Rate limiting is disabled.
7838b0946cSJonathan Doman         return false;
7938b0946cSJonathan Doman     }
8038b0946cSJonathan Doman 
8138b0946cSJonathan Doman     using Clock = sdeventplus::Clock<sdeventplus::ClockId::Monotonic>;
8238b0946cSJonathan Doman 
8338b0946cSJonathan Doman     static constexpr std::chrono::seconds rateLimitInterval(1);
8438b0946cSJonathan Doman     static unsigned int rateLimitCount = 0;
8538b0946cSJonathan Doman     static Clock::time_point rateLimitEndTime;
8638b0946cSJonathan Doman 
8738b0946cSJonathan Doman     const sdeventplus::Event& event = ioSource.get_event();
8838b0946cSJonathan Doman 
8938b0946cSJonathan Doman     if (rateLimitCount == 0)
9038b0946cSJonathan Doman     {
9138b0946cSJonathan Doman         // Initialize the end time when we start a new interval
9238b0946cSJonathan Doman         rateLimitEndTime = Clock(event).now() + rateLimitInterval;
9338b0946cSJonathan Doman     }
9438b0946cSJonathan Doman 
9538b0946cSJonathan Doman     if (++rateLimitCount < reporter.rateLimit)
9638b0946cSJonathan Doman     {
9738b0946cSJonathan Doman         return false;
9838b0946cSJonathan Doman     }
9938b0946cSJonathan Doman 
10038b0946cSJonathan Doman     rateLimitCount = 0;
10138b0946cSJonathan Doman 
10238b0946cSJonathan Doman     if (rateLimitEndTime < Clock(event).now())
10338b0946cSJonathan Doman     {
10438b0946cSJonathan Doman         return false;
10538b0946cSJonathan Doman     }
10638b0946cSJonathan Doman 
10738b0946cSJonathan Doman     if (verbose)
10838b0946cSJonathan Doman     {
10938b0946cSJonathan Doman         fprintf(stderr, "Hit POST code rate limit - disabling temporarily\n");
11038b0946cSJonathan Doman     }
11138b0946cSJonathan Doman 
11238b0946cSJonathan Doman     ioSource.set_enabled(sdeventplus::source::Enabled::Off);
11338b0946cSJonathan Doman     sdeventplus::source::Time<sdeventplus::ClockId::Monotonic>(
11438b0946cSJonathan Doman         event, rateLimitEndTime, std::chrono::milliseconds(100),
11538b0946cSJonathan Doman         [&ioSource](auto&, auto) {
11638b0946cSJonathan Doman             if (verbose)
11738b0946cSJonathan Doman             {
11838b0946cSJonathan Doman                 fprintf(stderr, "Reenabling POST code handler\n");
11938b0946cSJonathan Doman             }
12038b0946cSJonathan Doman             ioSource.set_enabled(sdeventplus::source::Enabled::On);
121d62ef559SPatrick Williams         })
122d62ef559SPatrick Williams         .set_floating(true);
12338b0946cSJonathan Doman     return true;
12438b0946cSJonathan Doman }
12538b0946cSJonathan Doman 
12633569758SPatrick Venture /*
12772d55072Scchoux  * Split input code into multiple 2 bytes PCC code, If the PCC code prefix
12872d55072Scchoux  * matches the check code, store each PCC code in aspeedPCCBuffer, or clear
12972d55072Scchoux  * aspeedPCCBuffer if the prefix does not match.
13072d55072Scchoux  *
13172d55072Scchoux  * Each PCC code contains one byte of port number (MSB) and another byte of
13272d55072Scchoux  * partial postcode (LSB). To get a complete postcode, the PCC code should
13372d55072Scchoux  * followed the sequence of 0x40AA, 0x41BB, 0x42CC & 0x43DD. When
13472d55072Scchoux  * aspeedPCCBuffer contains enough PCC codes, the postcode will be assigned as
13572d55072Scchoux  * 0xDDCCBBAA.
13672d55072Scchoux  */
aspeedPCC(std::vector<uint8_t> & code,ssize_t readb)137*fe51495eSCosmo Chou bool aspeedPCC(std::vector<uint8_t>& code, ssize_t readb)
13872d55072Scchoux {
13972d55072Scchoux     // Size of data coming from the PCC hardware
14072d55072Scchoux     constexpr size_t pccSize = sizeof(uint16_t);
14172d55072Scchoux     // Required PCC count of a full postcode, if codeSize is 8 bytes, it means
14272d55072Scchoux     // it require 4 PCC codes in correct sequence to get a complete postcode.
14372d55072Scchoux     const size_t fullPostPCCCount = codeSize / pccSize;
14472d55072Scchoux     // A PCC buffer for storing PCC code in sequence.
14572d55072Scchoux     static std::vector<uint16_t> aspeedPCCBuffer;
14672d55072Scchoux     constexpr uint16_t firstPCCPortNumber = 0x4000;
14772d55072Scchoux     constexpr uint16_t pccPortNumberMask = 0xFF00;
14872d55072Scchoux     constexpr uint16_t pccPostCodeMask = 0x00FF;
14972d55072Scchoux     constexpr uint8_t byteShift = 8;
15072d55072Scchoux 
151*fe51495eSCosmo Chou     uint16_t* codePtr = reinterpret_cast<uint16_t*>(code.data());
15272d55072Scchoux 
15372d55072Scchoux     for (size_t i = 0; i < (readb / pccSize); i++)
15472d55072Scchoux     {
155d62ef559SPatrick Williams         uint16_t checkCode =
156d62ef559SPatrick Williams             firstPCCPortNumber +
157d62ef559SPatrick Williams             ((aspeedPCCBuffer.size() % fullPostPCCCount) << byteShift);
15872d55072Scchoux 
15972d55072Scchoux         if (checkCode == (codePtr[i] & pccPortNumberMask))
16072d55072Scchoux         {
16172d55072Scchoux             aspeedPCCBuffer.emplace_back(codePtr[i]);
16272d55072Scchoux         }
16372d55072Scchoux         else
16472d55072Scchoux         {
16572d55072Scchoux             aspeedPCCBuffer.clear();
16672d55072Scchoux 
16772d55072Scchoux             // keep the PCC code if codePtr[i] matches with 0x40XX as first PCC
16872d55072Scchoux             // code in buffer.
16972d55072Scchoux             if ((codePtr[i] & pccPortNumberMask) == firstPCCPortNumber)
17072d55072Scchoux             {
17172d55072Scchoux                 aspeedPCCBuffer.emplace_back(codePtr[i]);
17272d55072Scchoux             }
17372d55072Scchoux         }
17472d55072Scchoux     }
17572d55072Scchoux 
17672d55072Scchoux     if (aspeedPCCBuffer.size() < fullPostPCCCount)
17772d55072Scchoux     {
17872d55072Scchoux         // not receive full postcode yet.
17972d55072Scchoux         return false;
18072d55072Scchoux     }
18172d55072Scchoux 
18272d55072Scchoux     // Remove the prefix bytes and combine the partial postcodes together.
183*fe51495eSCosmo Chou     code.clear();
184*fe51495eSCosmo Chou     for (size_t i = fullPostPCCCount; i > 0; --i)
18572d55072Scchoux     {
186*fe51495eSCosmo Chou         code.push_back(aspeedPCCBuffer[i - 1] & pccPostCodeMask);
18772d55072Scchoux     }
18872d55072Scchoux     aspeedPCCBuffer.erase(aspeedPCCBuffer.begin(),
18972d55072Scchoux                           aspeedPCCBuffer.begin() + fullPostPCCCount);
19072d55072Scchoux 
19172d55072Scchoux     return true;
19272d55072Scchoux }
19372d55072Scchoux 
19472d55072Scchoux /*
195eb31231eSKun Yi  * Callback handling IO event from the POST code fd. i.e. there is new
196eb31231eSKun Yi  * POST code available to read.
197eb31231eSKun Yi  */
PostCodeEventHandler(PostReporter * reporter,sdeventplus::source::IO & s,int postFd,uint32_t)19838b0946cSJonathan Doman void PostCodeEventHandler(PostReporter* reporter, sdeventplus::source::IO& s,
19938b0946cSJonathan Doman                           int postFd, uint32_t)
200eb31231eSKun Yi {
201*fe51495eSCosmo Chou     std::vector<uint8_t> code(codeSize, 0);
2020f964b49SWilliam A. Kennington III     ssize_t readb;
20338b0946cSJonathan Doman 
204*fe51495eSCosmo Chou     while ((readb = read(postFd, code.data(), codeSize)) > 0)
205eb31231eSKun Yi     {
20672d55072Scchoux         if (procPostCode && procPostCode(code, readb) == false)
20772d55072Scchoux         {
20872d55072Scchoux             return;
20972d55072Scchoux         }
21072d55072Scchoux 
21166efa632SWilliam A. Kennington III         if (verbose)
21266efa632SWilliam A. Kennington III         {
213*fe51495eSCosmo Chou             fprintf(stderr, "Code: 0x");
214*fe51495eSCosmo Chou             for (const auto& byte : code)
215*fe51495eSCosmo Chou             {
216*fe51495eSCosmo Chou                 fprintf(stderr, "%02x", byte);
217*fe51495eSCosmo Chou             }
218*fe51495eSCosmo Chou             fprintf(stderr, "\n");
21966efa632SWilliam A. Kennington III         }
220f21475a2SWilliam A. Kennington III         // HACK: Always send property changed signal even for the same code
221f21475a2SWilliam A. Kennington III         // since we are single threaded, external users will never see the
222f21475a2SWilliam A. Kennington III         // first value.
223*fe51495eSCosmo Chou         code[0] = ~code[0];
224*fe51495eSCosmo Chou         reporter->value(std::make_tuple(code, secondary_post_code_t{}), true);
225*fe51495eSCosmo Chou         code[0] = ~code[0];
226ba5258f7SManojkiran Eda         reporter->value(std::make_tuple(code, secondary_post_code_t{}));
2270f964b49SWilliam A. Kennington III 
228dd3928b0SManojkiran Eda         // read depends on old data being cleared since it doesn't always read
2290f964b49SWilliam A. Kennington III         // the full code size
230*fe51495eSCosmo Chou         code.resize(codeSize);
231*fe51495eSCosmo Chou         std::fill(code.begin(), code.end(), 0);
23238b0946cSJonathan Doman 
23338b0946cSJonathan Doman         if (rateLimit(*reporter, s))
23438b0946cSJonathan Doman         {
23538b0946cSJonathan Doman             return;
23638b0946cSJonathan Doman         }
237eb31231eSKun Yi     }
2380f964b49SWilliam A. Kennington III 
2390f964b49SWilliam A. Kennington III     if (readb < 0 && (errno == EAGAIN || errno == EWOULDBLOCK))
2400f964b49SWilliam A. Kennington III     {
2410f964b49SWilliam A. Kennington III         return;
2420f964b49SWilliam A. Kennington III     }
2430f964b49SWilliam A. Kennington III 
2440f964b49SWilliam A. Kennington III     /* Read failure. */
2450f964b49SWilliam A. Kennington III     if (readb == 0)
2460f964b49SWilliam A. Kennington III     {
2470f964b49SWilliam A. Kennington III         fprintf(stderr, "Unexpected EOF reading postcode\n");
2480f964b49SWilliam A. Kennington III     }
2490f964b49SWilliam A. Kennington III     else
2500f964b49SWilliam A. Kennington III     {
2510f964b49SWilliam A. Kennington III         fprintf(stderr, "Failed to read postcode: %s\n", strerror(errno));
2520f964b49SWilliam A. Kennington III     }
2530f964b49SWilliam A. Kennington III     s.get_event().exit(1);
254eb31231eSKun Yi }
255eb31231eSKun Yi 
256eb31231eSKun Yi /*
25733569758SPatrick Venture  * TODO(venture): this only listens one of the possible snoop ports, but
25833569758SPatrick Venture  * doesn't share the namespace.
25933569758SPatrick Venture  *
26033569758SPatrick Venture  * This polls() the lpc snoop character device and it owns the dbus object
26133569758SPatrick Venture  * whose value is the latest port 80h value.
26233569758SPatrick Venture  */
main(int argc,char * argv[])26333569758SPatrick Venture int main(int argc, char* argv[])
26433569758SPatrick Venture {
2650269eaf3SKumar Thangavel     int postFd = -1;
26638b0946cSJonathan Doman     unsigned int rateLimit = 0;
2670269eaf3SKumar Thangavel 
2680269eaf3SKumar Thangavel     int opt;
2690269eaf3SKumar Thangavel 
2700269eaf3SKumar Thangavel     std::vector<std::string> host;
27133569758SPatrick Venture 
2721ceb21bdSPatrick Venture     // clang-format off
273e7b07f08SBenjamin Fair     static const struct option long_options[] = {
2740269eaf3SKumar Thangavel #ifdef ENABLE_IPMI_SNOOP
2750269eaf3SKumar Thangavel         {"host", optional_argument, NULL, 'h'},
276de7a6dd7SJonathan Doman #else
277aade4adbSManojkiran Eda         {"device", optional_argument, NULL, 'd'},
27838b0946cSJonathan Doman         {"rate-limit", optional_argument, NULL, 'r'},
279de7a6dd7SJonathan Doman         {"bytes",  required_argument, NULL, 'b'},
280fd2430d8SJonathan Doman #endif
28166efa632SWilliam A. Kennington III         {"verbose", no_argument, NULL, 'v'},
2821ceb21bdSPatrick Venture         {0, 0, 0, 0}
2831ceb21bdSPatrick Venture     };
2841ceb21bdSPatrick Venture     // clang-format on
285e7b07f08SBenjamin Fair 
286de7a6dd7SJonathan Doman     constexpr const char* optstring =
287de7a6dd7SJonathan Doman #ifdef ENABLE_IPMI_SNOOP
288de7a6dd7SJonathan Doman         "h:"
289de7a6dd7SJonathan Doman #else
290de7a6dd7SJonathan Doman         "d:r:b:"
291de7a6dd7SJonathan Doman #endif
292de7a6dd7SJonathan Doman         "v";
293de7a6dd7SJonathan Doman 
294de7a6dd7SJonathan Doman     while ((opt = getopt_long(argc, argv, optstring, long_options, NULL)) != -1)
295e7b07f08SBenjamin Fair     {
296e7b07f08SBenjamin Fair         switch (opt)
297e7b07f08SBenjamin Fair         {
298e7b07f08SBenjamin Fair             case 0:
299e7b07f08SBenjamin Fair                 break;
3000ea7357eSPatrick Williams             case 'h':
3010ea7357eSPatrick Williams             {
3020269eaf3SKumar Thangavel                 std::string_view instances = optarg;
3030269eaf3SKumar Thangavel                 size_t pos = 0;
3040269eaf3SKumar Thangavel 
3050269eaf3SKumar Thangavel                 while ((pos = instances.find(" ")) != std::string::npos)
3060269eaf3SKumar Thangavel                 {
3070269eaf3SKumar Thangavel                     host.emplace_back(instances.substr(0, pos));
3080269eaf3SKumar Thangavel                     instances.remove_prefix(pos + 1);
3090269eaf3SKumar Thangavel                 }
3100269eaf3SKumar Thangavel                 host.emplace_back(instances);
3110269eaf3SKumar Thangavel                 break;
3120269eaf3SKumar Thangavel             }
3130ea7357eSPatrick Williams             case 'b':
3140ea7357eSPatrick Williams             {
315f69ad7e6SBenjamin Fair                 codeSize = atoi(optarg);
316f69ad7e6SBenjamin Fair 
317f69ad7e6SBenjamin Fair                 if (codeSize < 1 || codeSize > 8)
318f69ad7e6SBenjamin Fair                 {
319f69ad7e6SBenjamin Fair                     fprintf(stderr,
320f69ad7e6SBenjamin Fair                             "Invalid POST code size '%s'. Must be "
321f69ad7e6SBenjamin Fair                             "an integer from 1 to 8.\n",
322f69ad7e6SBenjamin Fair                             optarg);
323f69ad7e6SBenjamin Fair                     exit(EXIT_FAILURE);
324f69ad7e6SBenjamin Fair                 }
325f69ad7e6SBenjamin Fair                 break;
3260269eaf3SKumar Thangavel             }
327e7b07f08SBenjamin Fair             case 'd':
32895aa4440SRajaganesh Rathinasabapathi                 if (std::string(optarg).starts_with("/dev/aspeed-lpc-pcc"))
32972d55072Scchoux                 {
33072d55072Scchoux                     procPostCode = aspeedPCC;
33172d55072Scchoux                 }
3320269eaf3SKumar Thangavel 
333aade4adbSManojkiran Eda                 postFd = open(optarg, O_NONBLOCK);
334aade4adbSManojkiran Eda                 if (postFd < 0)
335aade4adbSManojkiran Eda                 {
336aade4adbSManojkiran Eda                     fprintf(stderr, "Unable to open: %s\n", optarg);
337aade4adbSManojkiran Eda                     return -1;
338aade4adbSManojkiran Eda                 }
339e7b07f08SBenjamin Fair                 break;
3400ea7357eSPatrick Williams             case 'r':
3410ea7357eSPatrick Williams             {
34238b0946cSJonathan Doman                 int argVal = -1;
34338b0946cSJonathan Doman                 try
34438b0946cSJonathan Doman                 {
34538b0946cSJonathan Doman                     argVal = std::stoi(optarg);
34638b0946cSJonathan Doman                 }
34738b0946cSJonathan Doman                 catch (...)
3480ea7357eSPatrick Williams                 {}
34938b0946cSJonathan Doman 
35038b0946cSJonathan Doman                 if (argVal < 1)
35138b0946cSJonathan Doman                 {
35238b0946cSJonathan Doman                     fprintf(stderr, "Invalid rate limit '%s'. Must be >= 1.\n",
35338b0946cSJonathan Doman                             optarg);
35438b0946cSJonathan Doman                     return EXIT_FAILURE;
35538b0946cSJonathan Doman                 }
35638b0946cSJonathan Doman 
35738b0946cSJonathan Doman                 rateLimit = static_cast<unsigned int>(argVal);
35838b0946cSJonathan Doman                 fprintf(stderr, "Rate limiting to %d POST codes per second.\n",
35938b0946cSJonathan Doman                         argVal);
36038b0946cSJonathan Doman                 break;
36138b0946cSJonathan Doman             }
36266efa632SWilliam A. Kennington III             case 'v':
36366efa632SWilliam A. Kennington III                 verbose = true;
36466efa632SWilliam A. Kennington III                 break;
365e7b07f08SBenjamin Fair             default:
366e7b07f08SBenjamin Fair                 usage(argv[0]);
36738b0946cSJonathan Doman                 return EXIT_FAILURE;
368e7b07f08SBenjamin Fair         }
369e7b07f08SBenjamin Fair     }
370e7b07f08SBenjamin Fair 
37133569758SPatrick Venture     auto bus = sdbusplus::bus::new_default();
37233569758SPatrick Venture 
3730269eaf3SKumar Thangavel #ifdef ENABLE_IPMI_SNOOP
3740269eaf3SKumar Thangavel     std::cout << "Verbose = " << verbose << std::endl;
3750269eaf3SKumar Thangavel     int ret = postCodeIpmiHandler(ipmiSnoopObject, snoopDbus, bus, host);
3760269eaf3SKumar Thangavel     if (ret < 0)
3770269eaf3SKumar Thangavel     {
3780269eaf3SKumar Thangavel         fprintf(stderr, "Error in postCodeIpmiHandler\n");
3790269eaf3SKumar Thangavel         return ret;
3800269eaf3SKumar Thangavel     }
3810269eaf3SKumar Thangavel     return 0;
3820269eaf3SKumar Thangavel #endif
3830269eaf3SKumar Thangavel 
3840269eaf3SKumar Thangavel     bool deferSignals = true;
3850269eaf3SKumar Thangavel 
38633569758SPatrick Venture     // Add systemd object manager.
387aebf87ccSPatrick Williams     sdbusplus::server::manager_t snoopdManager(bus, snoopObject);
38833569758SPatrick Venture 
38933569758SPatrick Venture     PostReporter reporter(bus, snoopObject, deferSignals);
39033569758SPatrick Venture     reporter.emit_object_added();
39133569758SPatrick Venture     bus.request_name(snoopDbus);
39233569758SPatrick Venture 
3931c16ad89SKun Yi     // Create sdevent and add IO source
3941c16ad89SKun Yi     try
3951c16ad89SKun Yi     {
3960269eaf3SKumar Thangavel         sdeventplus::Event event = sdeventplus::Event::get_default();
3974f26b3eeSHarvey.Wu         std::optional<sdeventplus::source::IO> reporterSource;
398aade4adbSManojkiran Eda         if (postFd > 0)
399aade4adbSManojkiran Eda         {
40038b0946cSJonathan Doman             reporter.rateLimit = rateLimit;
4014f26b3eeSHarvey.Wu             reporterSource.emplace(
40238b0946cSJonathan Doman                 event, postFd, EPOLLIN,
40338b0946cSJonathan Doman                 std::bind_front(PostCodeEventHandler, &reporter));
404aade4adbSManojkiran Eda         }
4051c16ad89SKun Yi         // Enable bus to handle incoming IO and bus events
40630751ec2SWilliam A. Kennington III         auto intCb = [](sdeventplus::source::Signal& source,
4076a5e0a1cSWilliam A. Kennington III                         const struct signalfd_siginfo*) {
4086a5e0a1cSWilliam A. Kennington III             source.get_event().exit(0);
4096a5e0a1cSWilliam A. Kennington III         };
4106a5e0a1cSWilliam A. Kennington III         stdplus::signal::block(SIGINT);
4116a5e0a1cSWilliam A. Kennington III         sdeventplus::source::Signal(event, SIGINT, intCb).set_floating(true);
4126a5e0a1cSWilliam A. Kennington III         stdplus::signal::block(SIGTERM);
4136a5e0a1cSWilliam A. Kennington III         sdeventplus::source::Signal(event, SIGTERM, std::move(intCb))
4146a5e0a1cSWilliam A. Kennington III             .set_floating(true);
41530751ec2SWilliam A. Kennington III         return sdeventplus::utility::loopWithBus(event, bus);
4161c16ad89SKun Yi     }
4171c16ad89SKun Yi     catch (const std::exception& e)
4181c16ad89SKun Yi     {
4191c16ad89SKun Yi         fprintf(stderr, "%s\n", e.what());
4201c16ad89SKun Yi     }
42133569758SPatrick Venture 
42233569758SPatrick Venture     if (postFd > -1)
42333569758SPatrick Venture     {
42433569758SPatrick Venture         close(postFd);
42533569758SPatrick Venture     }
42633569758SPatrick Venture 
42756127ef8SSunita Kumari     return 0;
42833569758SPatrick Venture }
429