blob: 74d807216011a31cf3b900fdb345afad5cfb5fa8 [file] [log] [blame]
Patrick Venture33569752018-03-12 18:56:14 -07001/**
2 * Copyright 2017 Google Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Patrick Ventureb5754fd2018-09-10 13:13:58 -070017#include "lpcsnoop/snoop.hpp"
18
William A. Kennington III6dac4c52019-12-13 15:05:00 -080019#include <endian.h>
Patrick Venture33569752018-03-12 18:56:14 -070020#include <fcntl.h>
Benjamin Faire7b07f02018-07-02 09:51:37 -070021#include <getopt.h>
Patrick Ventureb5754fd2018-09-10 13:13:58 -070022#include <sys/epoll.h>
23#include <systemd/sd-event.h>
Patrick Venture33569752018-03-12 18:56:14 -070024#include <unistd.h>
25
Patrick Venture33569752018-03-12 18:56:14 -070026#include <cstdint>
Kun Yi1c16ad82018-09-12 10:01:49 -070027#include <exception>
Patrick Venture33569752018-03-12 18:56:14 -070028#include <iostream>
29#include <memory>
Kun Yi1c16ad82018-09-12 10:01:49 -070030#include <sdeventplus/event.hpp>
31#include <sdeventplus/source/event.hpp>
32#include <sdeventplus/source/io.hpp>
Patrick Venture33569752018-03-12 18:56:14 -070033#include <thread>
34
Benjamin Fairf69ad7e2018-07-13 13:41:10 -070035static size_t codeSize = 1; /* Size of each POST code in bytes */
Benjamin Faire7b07f02018-07-02 09:51:37 -070036
Benjamin Faire7b07f02018-07-02 09:51:37 -070037static void usage(const char* name)
38{
39 fprintf(stderr,
40 "Usage: %s [-d <DEVICE>]\n"
Benjamin Fairf69ad7e2018-07-13 13:41:10 -070041 " -b, --bytes <SIZE> set POST code length to <SIZE> bytes. "
42 "Default is %zu\n"
Manojkiran Edaaade4ad2021-02-19 11:20:33 +053043 " -d, --device <DEVICE> use <DEVICE> file.\n"
William A. Kennington III66efa632020-04-16 18:46:20 -070044 " -v, --verbose Prints verbose information while running\n\n",
Manojkiran Edaaade4ad2021-02-19 11:20:33 +053045 name, codeSize);
Benjamin Fairf69ad7e2018-07-13 13:41:10 -070046}
47
Patrick Venture33569752018-03-12 18:56:14 -070048/*
Kun Yieb312312018-06-13 09:20:50 -070049 * Callback handling IO event from the POST code fd. i.e. there is new
50 * POST code available to read.
51 */
Kun Yicce09622020-04-06 14:01:55 -070052void PostCodeEventHandler(sdeventplus::source::IO& s, int postFd, uint32_t,
53 PostReporter* reporter, bool verbose)
Kun Yieb312312018-06-13 09:20:50 -070054{
William A. Kennington III6dac4c52019-12-13 15:05:00 -080055 uint64_t code = 0;
William A. Kennington III0f964b42020-04-16 18:46:03 -070056 ssize_t readb;
57 while ((readb = read(postFd, &code, codeSize)) > 0)
Kun Yi1c16ad82018-09-12 10:01:49 -070058 {
William A. Kennington IIIf21475a2019-12-13 17:21:24 -080059 code = le64toh(code);
William A. Kennington III66efa632020-04-16 18:46:20 -070060 if (verbose)
61 {
62 fprintf(stderr, "Code: 0x%" PRIx64 "\n", code);
63 }
William A. Kennington IIIf21475a2019-12-13 17:21:24 -080064 // HACK: Always send property changed signal even for the same code
65 // since we are single threaded, external users will never see the
66 // first value.
Manojkiran Edaba5258f2021-02-25 13:23:33 +053067 reporter->value(std::make_tuple(~code, secondary_post_code_t{}), true);
68 reporter->value(std::make_tuple(code, secondary_post_code_t{}));
William A. Kennington III0f964b42020-04-16 18:46:03 -070069
70 // read depends on old data being cleared since it doens't always read
71 // the full code size
72 code = 0;
Kun Yi1c16ad82018-09-12 10:01:49 -070073 }
William A. Kennington III0f964b42020-04-16 18:46:03 -070074
75 if (readb < 0 && (errno == EAGAIN || errno == EWOULDBLOCK))
76 {
77 return;
78 }
79
80 /* Read failure. */
81 if (readb == 0)
82 {
83 fprintf(stderr, "Unexpected EOF reading postcode\n");
84 }
85 else
86 {
87 fprintf(stderr, "Failed to read postcode: %s\n", strerror(errno));
88 }
89 s.get_event().exit(1);
Kun Yieb312312018-06-13 09:20:50 -070090}
91
92/*
Patrick Venture33569752018-03-12 18:56:14 -070093 * TODO(venture): this only listens one of the possible snoop ports, but
94 * doesn't share the namespace.
95 *
96 * This polls() the lpc snoop character device and it owns the dbus object
97 * whose value is the latest port 80h value.
98 */
99int main(int argc, char* argv[])
100{
101 int rc = 0;
Benjamin Faire7b07f02018-07-02 09:51:37 -0700102 int opt;
Patrick Venture33569752018-03-12 18:56:14 -0700103 int postFd = -1;
Patrick Venture33569752018-03-12 18:56:14 -0700104
105 /*
106 * These string constants are only used in this method within this object
107 * and this object is the only object feeding into the final binary.
108 *
109 * If however, another object is added to this binary it would be proper
110 * to move these declarations to be global and extern to the other object.
111 */
112 const char* snoopObject = SNOOP_OBJECTPATH;
113 const char* snoopDbus = SNOOP_BUSNAME;
Benjamin Faire7b07f02018-07-02 09:51:37 -0700114
Patrick Venture33569752018-03-12 18:56:14 -0700115 bool deferSignals = true;
William A. Kennington III66efa632020-04-16 18:46:20 -0700116 bool verbose = false;
Patrick Venture33569752018-03-12 18:56:14 -0700117
Patrick Venture1ceb21b2018-08-08 11:29:36 -0700118 // clang-format off
Benjamin Faire7b07f02018-07-02 09:51:37 -0700119 static const struct option long_options[] = {
Patrick Venture1ceb21b2018-08-08 11:29:36 -0700120 {"bytes", required_argument, NULL, 'b'},
Manojkiran Edaaade4ad2021-02-19 11:20:33 +0530121 {"device", optional_argument, NULL, 'd'},
William A. Kennington III66efa632020-04-16 18:46:20 -0700122 {"verbose", no_argument, NULL, 'v'},
Patrick Venture1ceb21b2018-08-08 11:29:36 -0700123 {0, 0, 0, 0}
124 };
125 // clang-format on
Benjamin Faire7b07f02018-07-02 09:51:37 -0700126
William A. Kennington III66efa632020-04-16 18:46:20 -0700127 while ((opt = getopt_long(argc, argv, "b:d:v", long_options, NULL)) != -1)
Benjamin Faire7b07f02018-07-02 09:51:37 -0700128 {
129 switch (opt)
130 {
131 case 0:
132 break;
Benjamin Fairf69ad7e2018-07-13 13:41:10 -0700133 case 'b':
134 codeSize = atoi(optarg);
135
136 if (codeSize < 1 || codeSize > 8)
137 {
138 fprintf(stderr,
139 "Invalid POST code size '%s'. Must be "
140 "an integer from 1 to 8.\n",
141 optarg);
142 exit(EXIT_FAILURE);
143 }
144 break;
Benjamin Faire7b07f02018-07-02 09:51:37 -0700145 case 'd':
Manojkiran Edaaade4ad2021-02-19 11:20:33 +0530146 postFd = open(optarg, O_NONBLOCK);
147 if (postFd < 0)
148 {
149 fprintf(stderr, "Unable to open: %s\n", optarg);
150 return -1;
151 }
152
Benjamin Faire7b07f02018-07-02 09:51:37 -0700153 break;
William A. Kennington III66efa632020-04-16 18:46:20 -0700154 case 'v':
155 verbose = true;
156 break;
Benjamin Faire7b07f02018-07-02 09:51:37 -0700157 default:
158 usage(argv[0]);
159 exit(EXIT_FAILURE);
160 }
161 }
162
Patrick Venture33569752018-03-12 18:56:14 -0700163 auto bus = sdbusplus::bus::new_default();
164
165 // Add systemd object manager.
166 sdbusplus::server::manager::manager(bus, snoopObject);
167
168 PostReporter reporter(bus, snoopObject, deferSignals);
Kun Yieb312312018-06-13 09:20:50 -0700169 reporter.emit_object_added();
170 bus.request_name(snoopDbus);
Kun Yieb312312018-06-13 09:20:50 -0700171
Kun Yi1c16ad82018-09-12 10:01:49 -0700172 // Create sdevent and add IO source
173 try
174 {
175 sdeventplus::Event event = sdeventplus::Event::get_default();
Troy Lee2a744b22021-04-01 22:53:30 +0800176 std::unique_ptr<sdeventplus::source::IO> reporterSource;
Manojkiran Edaaade4ad2021-02-19 11:20:33 +0530177 if (postFd > 0)
178 {
Troy Lee2a744b22021-04-01 22:53:30 +0800179 reporterSource = std::make_unique<sdeventplus::source::IO>(
Manojkiran Edaaade4ad2021-02-19 11:20:33 +0530180 event, postFd, EPOLLIN | EPOLLET,
181 std::bind(PostCodeEventHandler, std::placeholders::_1,
182 std::placeholders::_2, std::placeholders::_3,
183 &reporter, verbose));
184 }
Kun Yi1c16ad82018-09-12 10:01:49 -0700185 // Enable bus to handle incoming IO and bus events
186 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
187 rc = event.loop();
188 }
189 catch (const std::exception& e)
190 {
191 fprintf(stderr, "%s\n", e.what());
192 }
Kun Yieb312312018-06-13 09:20:50 -0700193
Patrick Venture33569752018-03-12 18:56:14 -0700194 if (postFd > -1)
195 {
196 close(postFd);
197 }
198
Patrick Venture33569752018-03-12 18:56:14 -0700199 return rc;
200}