blob: 1094e4302f4f5a263c71cf70bbe675063b6e4073 [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 Faire7b07f02018-07-02 09:51:37 -070035static const char* snoopFilename = "/dev/aspeed-lpc-snoop0";
Benjamin Fairf69ad7e2018-07-13 13:41:10 -070036static size_t codeSize = 1; /* Size of each POST code in bytes */
Benjamin Faire7b07f02018-07-02 09:51:37 -070037
Benjamin Faire7b07f02018-07-02 09:51:37 -070038static void usage(const char* name)
39{
40 fprintf(stderr,
41 "Usage: %s [-d <DEVICE>]\n"
Benjamin Fairf69ad7e2018-07-13 13:41:10 -070042 " -b, --bytes <SIZE> set POST code length to <SIZE> bytes. "
43 "Default is %zu\n"
William A. Kennington III66efa632020-04-16 18:46:20 -070044 " -d, --device <DEVICE> use <DEVICE> file. Default is '%s'\n"
45 " -v, --verbose Prints verbose information while running\n\n",
Benjamin Fairf69ad7e2018-07-13 13:41:10 -070046 name, codeSize, snoopFilename);
47}
48
Patrick Venture33569752018-03-12 18:56:14 -070049/*
Kun Yieb312312018-06-13 09:20:50 -070050 * Callback handling IO event from the POST code fd. i.e. there is new
51 * POST code available to read.
52 */
Kun Yicce09622020-04-06 14:01:55 -070053void PostCodeEventHandler(sdeventplus::source::IO& s, int postFd, uint32_t,
54 PostReporter* reporter, bool verbose)
Kun Yieb312312018-06-13 09:20:50 -070055{
William A. Kennington III6dac4c52019-12-13 15:05:00 -080056 uint64_t code = 0;
William A. Kennington III0f964b42020-04-16 18:46:03 -070057 ssize_t readb;
58 while ((readb = read(postFd, &code, codeSize)) > 0)
Kun Yi1c16ad82018-09-12 10:01:49 -070059 {
William A. Kennington IIIf21475a2019-12-13 17:21:24 -080060 code = le64toh(code);
William A. Kennington III66efa632020-04-16 18:46:20 -070061 if (verbose)
62 {
63 fprintf(stderr, "Code: 0x%" PRIx64 "\n", code);
64 }
William A. Kennington IIIf21475a2019-12-13 17:21:24 -080065 // HACK: Always send property changed signal even for the same code
66 // since we are single threaded, external users will never see the
67 // first value.
68 reporter->value(~code, true);
69 reporter->value(code);
William A. Kennington III0f964b42020-04-16 18:46:03 -070070
71 // read depends on old data being cleared since it doens't always read
72 // the full code size
73 code = 0;
Kun Yi1c16ad82018-09-12 10:01:49 -070074 }
William A. Kennington III0f964b42020-04-16 18:46:03 -070075
76 if (readb < 0 && (errno == EAGAIN || errno == EWOULDBLOCK))
77 {
78 return;
79 }
80
81 /* Read failure. */
82 if (readb == 0)
83 {
84 fprintf(stderr, "Unexpected EOF reading postcode\n");
85 }
86 else
87 {
88 fprintf(stderr, "Failed to read postcode: %s\n", strerror(errno));
89 }
90 s.get_event().exit(1);
Kun Yieb312312018-06-13 09:20:50 -070091}
92
93/*
Patrick Venture33569752018-03-12 18:56:14 -070094 * TODO(venture): this only listens one of the possible snoop ports, but
95 * doesn't share the namespace.
96 *
97 * This polls() the lpc snoop character device and it owns the dbus object
98 * whose value is the latest port 80h value.
99 */
100int main(int argc, char* argv[])
101{
102 int rc = 0;
Benjamin Faire7b07f02018-07-02 09:51:37 -0700103 int opt;
Patrick Venture33569752018-03-12 18:56:14 -0700104 int postFd = -1;
Patrick Venture33569752018-03-12 18:56:14 -0700105
106 /*
107 * These string constants are only used in this method within this object
108 * and this object is the only object feeding into the final binary.
109 *
110 * If however, another object is added to this binary it would be proper
111 * to move these declarations to be global and extern to the other object.
112 */
113 const char* snoopObject = SNOOP_OBJECTPATH;
114 const char* snoopDbus = SNOOP_BUSNAME;
Benjamin Faire7b07f02018-07-02 09:51:37 -0700115
Patrick Venture33569752018-03-12 18:56:14 -0700116 bool deferSignals = true;
William A. Kennington III66efa632020-04-16 18:46:20 -0700117 bool verbose = false;
Patrick Venture33569752018-03-12 18:56:14 -0700118
Patrick Venture1ceb21b2018-08-08 11:29:36 -0700119 // clang-format off
Benjamin Faire7b07f02018-07-02 09:51:37 -0700120 static const struct option long_options[] = {
Patrick Venture1ceb21b2018-08-08 11:29:36 -0700121 {"bytes", required_argument, NULL, 'b'},
Benjamin Fairf69ad7e2018-07-13 13:41:10 -0700122 {"device", required_argument, NULL, 'd'},
William A. Kennington III66efa632020-04-16 18:46:20 -0700123 {"verbose", no_argument, NULL, 'v'},
Patrick Venture1ceb21b2018-08-08 11:29:36 -0700124 {0, 0, 0, 0}
125 };
126 // clang-format on
Benjamin Faire7b07f02018-07-02 09:51:37 -0700127
William A. Kennington III66efa632020-04-16 18:46:20 -0700128 while ((opt = getopt_long(argc, argv, "b:d:v", long_options, NULL)) != -1)
Benjamin Faire7b07f02018-07-02 09:51:37 -0700129 {
130 switch (opt)
131 {
132 case 0:
133 break;
Benjamin Fairf69ad7e2018-07-13 13:41:10 -0700134 case 'b':
135 codeSize = atoi(optarg);
136
137 if (codeSize < 1 || codeSize > 8)
138 {
139 fprintf(stderr,
140 "Invalid POST code size '%s'. Must be "
141 "an integer from 1 to 8.\n",
142 optarg);
143 exit(EXIT_FAILURE);
144 }
145 break;
Benjamin Faire7b07f02018-07-02 09:51:37 -0700146 case 'd':
147 snoopFilename = optarg;
148 break;
William A. Kennington III66efa632020-04-16 18:46:20 -0700149 case 'v':
150 verbose = true;
151 break;
Benjamin Faire7b07f02018-07-02 09:51:37 -0700152 default:
153 usage(argv[0]);
154 exit(EXIT_FAILURE);
155 }
156 }
157
Tim Leee4090de2019-11-26 13:57:43 +0800158 postFd = open(snoopFilename, O_NONBLOCK);
Patrick Venture33569752018-03-12 18:56:14 -0700159 if (postFd < 0)
160 {
161 fprintf(stderr, "Unable to open: %s\n", snoopFilename);
162 return -1;
163 }
164
Patrick Venture33569752018-03-12 18:56:14 -0700165 auto bus = sdbusplus::bus::new_default();
166
167 // Add systemd object manager.
168 sdbusplus::server::manager::manager(bus, snoopObject);
169
170 PostReporter reporter(bus, snoopObject, deferSignals);
Kun Yieb312312018-06-13 09:20:50 -0700171 reporter.emit_object_added();
172 bus.request_name(snoopDbus);
Kun Yieb312312018-06-13 09:20:50 -0700173
Kun Yi1c16ad82018-09-12 10:01:49 -0700174 // Create sdevent and add IO source
175 try
176 {
177 sdeventplus::Event event = sdeventplus::Event::get_default();
178 sdeventplus::source::IO reporterSource(
William A. Kennington III0f964b42020-04-16 18:46:03 -0700179 event, postFd, EPOLLIN | EPOLLET,
Kun Yi1c16ad82018-09-12 10:01:49 -0700180 std::bind(PostCodeEventHandler, std::placeholders::_1,
William A. Kennington III66efa632020-04-16 18:46:20 -0700181 std::placeholders::_2, std::placeholders::_3, &reporter,
182 verbose));
Kun Yi1c16ad82018-09-12 10:01:49 -0700183 // Enable bus to handle incoming IO and bus events
184 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
185 rc = event.loop();
186 }
187 catch (const std::exception& e)
188 {
189 fprintf(stderr, "%s\n", e.what());
190 }
Kun Yieb312312018-06-13 09:20:50 -0700191
Patrick Venture33569752018-03-12 18:56:14 -0700192 if (postFd > -1)
193 {
194 close(postFd);
195 }
196
Patrick Venture33569752018-03-12 18:56:14 -0700197 return rc;
198}