xref: /openbmc/obmc-console/console-server.h (revision b965c220)
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 	void (*deselect)(struct handler *handler);
56 };
57 
58 struct handler {
59 	const struct handler_type *type;
60 };
61 
62 /* NOLINTBEGIN(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp) */
63 #define __handler_name(n) __handler_##n
64 #define _handler_name(n)  __handler_name(n)
65 
66 #ifndef __clang__
67 #define handler_type_check(h) BUILD_ASSERT_OR_ZERO((h)->init && (h)->fini)
68 #else
69 /* clang doesn't seem to be able to constify the type ops */
70 #define handler_type_check(h) 0
71 #endif
72 
73 #define console_handler_register(h)                                            \
74 	static const __attribute__((section("handlers")))                      \
75 	__attribute__((used)) struct handler_type *                            \
76 	_handler_name(__COUNTER__) = (h) + handler_type_check(h)
77 /* NOLINTEND(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp) */
78 
79 int console_data_out(struct console *console, const uint8_t *data, size_t len);
80 
81 enum poller_ret {
82 	POLLER_OK = 0,
83 	POLLER_REMOVE,
84 	POLLER_EXIT,
85 };
86 
87 typedef char(socket_path_t)[sizeof(((struct sockaddr_un *)NULL)->sun_path)];
88 
89 typedef enum poller_ret (*poller_event_fn_t)(struct handler *handler,
90 					     int revents, void *data);
91 typedef enum poller_ret (*poller_timeout_fn_t)(struct handler *handler,
92 					       void *data);
93 
94 enum tty_device {
95 	TTY_DEVICE_UNDEFINED = 0,
96 	TTY_DEVICE_VUART,
97 	TTY_DEVICE_UART,
98 	TTY_DEVICE_PTY,
99 };
100 
101 struct console_server {
102 	struct {
103 		const char *kname;
104 		char *dev;
105 		int fd;
106 		enum tty_device type;
107 		union {
108 			struct {
109 				char *sysfs_devnode;
110 				int sirq;
111 				uint16_t lpc_addr;
112 			} vuart;
113 			struct {
114 				speed_t baud;
115 			} uart;
116 		};
117 	} tty;
118 
119 	// All the pollfds are stored here,
120 	// so 'poll' can operate on them.
121 	// The other 'pollfd*' are just pointers to this array.
122 	struct pollfd *pollfds;
123 	size_t capacity_pollfds;
124 
125 	// index into pollfds
126 	size_t tty_pollfd_index;
127 
128 	struct config *config;
129 
130 	// the currently active console
131 	struct console *active;
132 
133 	struct console **consoles;
134 	size_t n_consoles;
135 
136 	// index into (struct console_server)->pollfds
137 	size_t dbus_pollfd_index;
138 
139 	struct sd_bus *bus;
140 
141 	// may be NULL in case there is no mux
142 	struct console_mux *mux;
143 };
144 
145 struct console {
146 	// point back to the console server
147 	// which we are a member of
148 	struct console_server *server;
149 
150 	const char *console_id;
151 
152 	/* Socket name starts with null character hence we need length */
153 	socket_path_t socket_name;
154 	ssize_t socket_name_len;
155 
156 	struct ringbuffer *rb;
157 
158 	struct handler **handlers;
159 	long n_handlers;
160 
161 	struct poller **pollers;
162 	long n_pollers;
163 
164 	// values to configure the mux
165 	unsigned long mux_index;
166 };
167 
168 /* poller API */
169 struct poller {
170 	struct handler *handler;
171 	void *data;
172 	poller_event_fn_t event_fn;
173 	poller_timeout_fn_t timeout_fn;
174 	struct timeval timeout;
175 	bool remove;
176 
177 	// index into (struct console_server)->pollfds
178 	size_t pollfd_index;
179 };
180 
181 struct poller *console_poller_register(struct console *console,
182 				       struct handler *handler,
183 				       poller_event_fn_t poller_fn,
184 				       poller_timeout_fn_t timeout_fn, int fd,
185 				       int events, void *data);
186 
187 void console_poller_unregister(struct console *console, struct poller *poller);
188 
189 void console_poller_set_events(struct console *console, struct poller *poller,
190 			       int events);
191 
192 void console_poller_set_timeout(struct console *console, struct poller *poller,
193 				const struct timeval *tv);
194 
195 /* ringbuffer API */
196 
197 enum ringbuffer_poll_ret {
198 	RINGBUFFER_POLL_OK = 0,
199 	RINGBUFFER_POLL_REMOVE,
200 };
201 
202 typedef enum ringbuffer_poll_ret (*ringbuffer_poll_fn_t)(void *data,
203 							 size_t force_len);
204 
205 struct ringbuffer_consumer;
206 
207 struct ringbuffer {
208 	uint8_t *buf;
209 	size_t size;
210 	size_t tail;
211 	struct ringbuffer_consumer **consumers;
212 	int n_consumers;
213 };
214 
215 struct ringbuffer_consumer {
216 	struct ringbuffer *rb;
217 	ringbuffer_poll_fn_t poll_fn;
218 	void *poll_data;
219 	size_t pos;
220 };
221 
222 struct ringbuffer *ringbuffer_init(size_t size);
223 void ringbuffer_fini(struct ringbuffer *rb);
224 
225 struct ringbuffer_consumer *
226 ringbuffer_consumer_register(struct ringbuffer *rb,
227 			     ringbuffer_poll_fn_t poll_fn, void *data);
228 
229 void ringbuffer_consumer_unregister(struct ringbuffer_consumer *rbc);
230 
231 int ringbuffer_queue(struct ringbuffer *rb, uint8_t *data, size_t len);
232 
233 size_t ringbuffer_dequeue_peek(struct ringbuffer_consumer *rbc, size_t offset,
234 			       uint8_t **data);
235 
236 int ringbuffer_dequeue_commit(struct ringbuffer_consumer *rbc, size_t len);
237 
238 size_t ringbuffer_len(struct ringbuffer_consumer *rbc);
239 
240 /* console wrapper around ringbuffer consumer registration */
241 struct ringbuffer_consumer *
242 console_ringbuffer_consumer_register(struct console *console,
243 				     ringbuffer_poll_fn_t poll_fn, void *data);
244 
245 /* Console server API */
246 void tty_init_termios(struct console_server *server);
247 
248 /* socket paths */
249 ssize_t console_socket_path(socket_path_t path, const char *id);
250 ssize_t console_socket_path_readable(const struct sockaddr_un *addr,
251 				     size_t addrlen, socket_path_t path);
252 
253 /* utils */
254 int write_buf_to_fd(int fd, const uint8_t *buf, size_t len);
255 
256 /* console_server dbus */
257 int dbus_server_init(struct console_server *server);
258 void dbus_server_fini(struct console_server *server);
259 
260 /* console-dbus API */
261 int dbus_init(struct console *console,
262 	      struct config *config __attribute__((unused)));
263 
264 /* socket-handler API */
265 int dbus_create_socket_consumer(struct console *console);
266 
267 #ifndef offsetof
268 #define offsetof(type, member) ((unsigned long)&((type *)NULL)->member)
269 #endif
270 
271 #define container_of(ptr, type, member)                                        \
272 	((type *)((void *)((ptr) - offsetof(type, member))))
273 
274 #define BUILD_ASSERT(c)                                                        \
275 	do {                                                                   \
276 		char __c[(c) ? 1 : -1] __attribute__((unused));                \
277 	} while (0)
278 
279 #define BUILD_ASSERT_OR_ZERO(c) (sizeof(char[(c) ? 1 : -1]) - 1)
280 
281 // returns the index of that pollfd in server->pollfds
282 // we cannot return a pointer because 'realloc' may move server->pollfds
283 ssize_t console_server_request_pollfd(struct console_server *server, int fd,
284 				      short int events);
285 
286 int console_server_release_pollfd(struct console_server *server,
287 				  size_t pollfd_index);
288