xref: /openbmc/obmc-console/console-server.h (revision 2325d5d5)
1 /**
2  * Copyright © 2016 IBM Corporation
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 
17 #pragma once
18 
19 #include <poll.h>
20 #include <stdbool.h>
21 #include <stdint.h>
22 #include <termios.h> /* for speed_t */
23 #include <time.h>
24 #include <systemd/sd-bus.h>
25 #include <sys/time.h>
26 #include <sys/un.h>
27 
28 struct console;
29 struct config;
30 
31 /* Handler API.
32  *
33  * Console data handlers: these implement the functions that process
34  * data coming out of the main tty device.
35  *
36  * Handlers are registered at link time using the console_handler_register()
37  * macro. We call each handler's ->init() function at startup, and ->fini() at
38  * exit.
39  *
40  * Handlers will almost always want to register a ringbuffer consumer, which
41  * provides data coming from the tty. Use cosole_register_ringbuffer_consumer()
42  * for this. To send data to the tty, use console_data_out().
43  *
44  * If a handler needs to monitor a separate file descriptor for events, use the
45  * poller API, through console_poller_register().
46  */
47 struct handler;
48 
49 struct handler_type {
50 	const char *name;
51 	struct handler *(*init)(const struct handler_type *type,
52 				struct console *console, struct config *config);
53 	void (*fini)(struct handler *handler);
54 	int (*baudrate)(struct handler *handler, speed_t baudrate);
55 };
56 
57 struct handler {
58 	const struct handler_type *type;
59 };
60 
61 /* NOLINTBEGIN(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp) */
62 #define __handler_name(n) __handler_##n
63 #define _handler_name(n)  __handler_name(n)
64 
65 #ifndef __clang__
66 #define handler_type_check(h) BUILD_ASSERT_OR_ZERO((h)->init && (h)->fini)
67 #else
68 /* clang doesn't seem to be able to constify the type ops */
69 #define handler_type_check(h) 0
70 #endif
71 
72 #define console_handler_register(h)                                            \
73 	static const __attribute__((section("handlers")))                      \
74 	__attribute__((used)) struct handler_type *                            \
75 	_handler_name(__COUNTER__) = (h) + handler_type_check(h)
76 /* NOLINTEND(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp) */
77 
78 int console_data_out(struct console *console, const uint8_t *data, size_t len);
79 
80 enum poller_ret {
81 	POLLER_OK = 0,
82 	POLLER_REMOVE,
83 	POLLER_EXIT,
84 };
85 
86 typedef char(socket_path_t)[sizeof(((struct sockaddr_un *)NULL)->sun_path)];
87 
88 typedef enum poller_ret (*poller_event_fn_t)(struct handler *handler,
89 					     int revents, void *data);
90 typedef enum poller_ret (*poller_timeout_fn_t)(struct handler *handler,
91 					       void *data);
92 
93 enum tty_device {
94 	TTY_DEVICE_UNDEFINED = 0,
95 	TTY_DEVICE_VUART,
96 	TTY_DEVICE_UART,
97 	TTY_DEVICE_PTY,
98 };
99 
100 struct console_server {
101 	struct {
102 		const char *kname;
103 		char *dev;
104 		int fd;
105 		enum tty_device type;
106 		union {
107 			struct {
108 				char *sysfs_devnode;
109 				int sirq;
110 				uint16_t lpc_addr;
111 			} vuart;
112 			struct {
113 				speed_t baud;
114 			} uart;
115 		};
116 	} tty;
117 
118 	// All the pollfds are stored here,
119 	// so 'poll' can operate on them.
120 	// The other 'pollfd*' are just pointers to this array.
121 	struct pollfd *pollfds;
122 	size_t capacity_pollfds;
123 
124 	// index into pollfds
125 	size_t tty_pollfd_index;
126 
127 	struct console *active;
128 };
129 
130 struct console {
131 	// point back to the console server
132 	// which we are a member of
133 	struct console_server *server;
134 
135 	const char *console_id;
136 
137 	/* Socket name starts with null character hence we need length */
138 	socket_path_t socket_name;
139 	ssize_t socket_name_len;
140 
141 	struct ringbuffer *rb;
142 
143 	struct handler **handlers;
144 	long n_handlers;
145 
146 	struct poller **pollers;
147 	long n_pollers;
148 
149 	// index into (struct console_server)->pollfds
150 	size_t dbus_pollfd_index;
151 
152 	struct sd_bus *bus;
153 };
154 
155 /* poller API */
156 struct poller {
157 	struct handler *handler;
158 	void *data;
159 	poller_event_fn_t event_fn;
160 	poller_timeout_fn_t timeout_fn;
161 	struct timeval timeout;
162 	bool remove;
163 
164 	// index into (struct console_server)->pollfds
165 	size_t pollfd_index;
166 };
167 
168 struct poller *console_poller_register(struct console *console,
169 				       struct handler *handler,
170 				       poller_event_fn_t poller_fn,
171 				       poller_timeout_fn_t timeout_fn, int fd,
172 				       int events, void *data);
173 
174 void console_poller_unregister(struct console *console, struct poller *poller);
175 
176 void console_poller_set_events(struct console *console, struct poller *poller,
177 			       int events);
178 
179 void console_poller_set_timeout(struct console *console, struct poller *poller,
180 				const struct timeval *tv);
181 
182 /* ringbuffer API */
183 
184 enum ringbuffer_poll_ret {
185 	RINGBUFFER_POLL_OK = 0,
186 	RINGBUFFER_POLL_REMOVE,
187 };
188 
189 typedef enum ringbuffer_poll_ret (*ringbuffer_poll_fn_t)(void *data,
190 							 size_t force_len);
191 
192 struct ringbuffer_consumer;
193 
194 struct ringbuffer {
195 	uint8_t *buf;
196 	size_t size;
197 	size_t tail;
198 	struct ringbuffer_consumer **consumers;
199 	int n_consumers;
200 };
201 
202 struct ringbuffer_consumer {
203 	struct ringbuffer *rb;
204 	ringbuffer_poll_fn_t poll_fn;
205 	void *poll_data;
206 	size_t pos;
207 };
208 
209 struct ringbuffer *ringbuffer_init(size_t size);
210 void ringbuffer_fini(struct ringbuffer *rb);
211 
212 struct ringbuffer_consumer *
213 ringbuffer_consumer_register(struct ringbuffer *rb,
214 			     ringbuffer_poll_fn_t poll_fn, void *data);
215 
216 void ringbuffer_consumer_unregister(struct ringbuffer_consumer *rbc);
217 
218 int ringbuffer_queue(struct ringbuffer *rb, uint8_t *data, size_t len);
219 
220 size_t ringbuffer_dequeue_peek(struct ringbuffer_consumer *rbc, size_t offset,
221 			       uint8_t **data);
222 
223 int ringbuffer_dequeue_commit(struct ringbuffer_consumer *rbc, size_t len);
224 
225 size_t ringbuffer_len(struct ringbuffer_consumer *rbc);
226 
227 /* console wrapper around ringbuffer consumer registration */
228 struct ringbuffer_consumer *
229 console_ringbuffer_consumer_register(struct console *console,
230 				     ringbuffer_poll_fn_t poll_fn, void *data);
231 
232 /* Console server API */
233 void tty_init_termios(struct console_server *server);
234 
235 /* socket paths */
236 ssize_t console_socket_path(socket_path_t path, const char *id);
237 ssize_t console_socket_path_readable(const struct sockaddr_un *addr,
238 				     size_t addrlen, socket_path_t path);
239 
240 /* utils */
241 int write_buf_to_fd(int fd, const uint8_t *buf, size_t len);
242 
243 /* console-dbus API */
244 int dbus_init(struct console *console,
245 	      struct config *config __attribute__((unused)));
246 
247 /* socket-handler API */
248 int dbus_create_socket_consumer(struct console *console);
249 
250 #ifndef offsetof
251 #define offsetof(type, member) ((unsigned long)&((type *)NULL)->member)
252 #endif
253 
254 #define container_of(ptr, type, member)                                        \
255 	((type *)((void *)((ptr)-offsetof(type, member))))
256 
257 #define BUILD_ASSERT(c)                                                        \
258 	do {                                                                   \
259 		char __c[(c) ? 1 : -1] __attribute__((unused));                \
260 	} while (0)
261 
262 #define BUILD_ASSERT_OR_ZERO(c) (sizeof(char[(c) ? 1 : -1]) - 1)
263 
264 // returns the index of that pollfd in server->pollfds
265 // we cannot return a pointer because 'realloc' may move server->pollfds
266 ssize_t console_server_request_pollfd(struct console_server *server, int fd,
267 				      short int events);
268 
269 int console_server_release_pollfd(struct console_server *server,
270 				  size_t pollfd_index);
271