xref: /openbmc/obmc-console/console-server.h (revision d6e8b64a)
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 	const char *name;
49 	int (*init)(struct handler *handler, struct console *console,
50 		    struct config *config);
51 	void (*fini)(struct handler *handler);
52 	int (*baudrate)(struct handler *handler, speed_t baudrate);
53 	bool active;
54 };
55 
56 /* NOLINTBEGIN(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp) */
57 #define __handler_name(n) __handler_##n
58 #define _handler_name(n)  __handler_name(n)
59 
60 #define console_handler_register(h)                                            \
61 	static const __attribute__((section("handlers")))                      \
62 	__attribute__((used)) struct handler *                                 \
63 	_handler_name(__COUNTER__) = h
64 /* NOLINTEND(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp) */
65 
66 int console_data_out(struct console *console, const uint8_t *data, size_t len);
67 
68 enum poller_ret {
69 	POLLER_OK = 0,
70 	POLLER_REMOVE,
71 	POLLER_EXIT,
72 };
73 
74 typedef char(socket_path_t)[sizeof(((struct sockaddr_un *)NULL)->sun_path)];
75 
76 typedef enum poller_ret (*poller_event_fn_t)(struct handler *handler,
77 					     int revents, void *data);
78 typedef enum poller_ret (*poller_timeout_fn_t)(struct handler *handler,
79 					       void *data);
80 
81 enum tty_device {
82 	TTY_DEVICE_UNDEFINED = 0,
83 	TTY_DEVICE_VUART,
84 	TTY_DEVICE_UART,
85 	TTY_DEVICE_PTY,
86 };
87 
88 /* Console server structure */
89 struct console {
90 	struct {
91 		const char *kname;
92 		char *dev;
93 		int fd;
94 		enum tty_device type;
95 		union {
96 			struct {
97 				char *sysfs_devnode;
98 				int sirq;
99 				uint16_t lpc_addr;
100 			} vuart;
101 			struct {
102 				speed_t baud;
103 			} uart;
104 		};
105 	} tty;
106 	const char *console_id;
107 
108 	/* Socket name starts with null character hence we need length */
109 	socket_path_t socket_name;
110 	ssize_t socket_name_len;
111 
112 	struct ringbuffer *rb;
113 
114 	struct handler **handlers;
115 	long n_handlers;
116 
117 	struct poller **pollers;
118 	long n_pollers;
119 
120 	struct pollfd *pollfds;
121 	struct sd_bus *bus;
122 };
123 
124 /* poller API */
125 struct poller {
126 	struct handler *handler;
127 	void *data;
128 	poller_event_fn_t event_fn;
129 	poller_timeout_fn_t timeout_fn;
130 	struct timeval timeout;
131 	bool remove;
132 };
133 
134 /* we have two extra entry in the pollfds array for the VUART tty */
135 enum internal_pollfds {
136 	POLLFD_HOSTTTY = 0,
137 	POLLFD_DBUS = 1,
138 	MAX_INTERNAL_POLLFD = 2,
139 };
140 
141 struct poller *console_poller_register(struct console *console,
142 				       struct handler *handler,
143 				       poller_event_fn_t poller_fn,
144 				       poller_timeout_fn_t timeout_fn, int fd,
145 				       int events, void *data);
146 
147 void console_poller_unregister(struct console *console, struct poller *poller);
148 
149 void console_poller_set_events(struct console *console, struct poller *poller,
150 			       int events);
151 
152 void console_poller_set_timeout(struct console *console, struct poller *poller,
153 				const struct timeval *tv);
154 
155 /* ringbuffer API */
156 
157 enum ringbuffer_poll_ret {
158 	RINGBUFFER_POLL_OK = 0,
159 	RINGBUFFER_POLL_REMOVE,
160 };
161 
162 typedef enum ringbuffer_poll_ret (*ringbuffer_poll_fn_t)(void *data,
163 							 size_t force_len);
164 
165 struct ringbuffer_consumer;
166 
167 struct ringbuffer {
168 	uint8_t *buf;
169 	size_t size;
170 	size_t tail;
171 	struct ringbuffer_consumer **consumers;
172 	int n_consumers;
173 };
174 
175 struct ringbuffer_consumer {
176 	struct ringbuffer *rb;
177 	ringbuffer_poll_fn_t poll_fn;
178 	void *poll_data;
179 	size_t pos;
180 };
181 
182 struct ringbuffer *ringbuffer_init(size_t size);
183 void ringbuffer_fini(struct ringbuffer *rb);
184 
185 struct ringbuffer_consumer *
186 ringbuffer_consumer_register(struct ringbuffer *rb,
187 			     ringbuffer_poll_fn_t poll_fn, void *data);
188 
189 void ringbuffer_consumer_unregister(struct ringbuffer_consumer *rbc);
190 
191 int ringbuffer_queue(struct ringbuffer *rb, uint8_t *data, size_t len);
192 
193 size_t ringbuffer_dequeue_peek(struct ringbuffer_consumer *rbc, size_t offset,
194 			       uint8_t **data);
195 
196 int ringbuffer_dequeue_commit(struct ringbuffer_consumer *rbc, size_t len);
197 
198 size_t ringbuffer_len(struct ringbuffer_consumer *rbc);
199 
200 /* console wrapper around ringbuffer consumer registration */
201 struct ringbuffer_consumer *
202 console_ringbuffer_consumer_register(struct console *console,
203 				     ringbuffer_poll_fn_t poll_fn, void *data);
204 
205 /* Console server API */
206 void tty_init_termios(struct console *console);
207 
208 /* config API */
209 struct config;
210 const char *config_get_value(struct config *config, const char *name);
211 struct config *config_init(const char *filename);
212 const char *config_resolve_console_id(struct config *config,
213 				      const char *id_arg);
214 void config_fini(struct config *config);
215 
216 int config_parse_baud(speed_t *speed, const char *baud_string);
217 uint32_t parse_baud_to_int(speed_t speed);
218 speed_t parse_int_to_baud(uint32_t baud);
219 int config_parse_bytesize(const char *size_str, size_t *size);
220 
221 /* socket paths */
222 ssize_t console_socket_path(socket_path_t path, const char *id);
223 ssize_t console_socket_path_readable(const struct sockaddr_un *addr,
224 				     size_t addrlen, socket_path_t path);
225 
226 /* utils */
227 int write_buf_to_fd(int fd, const uint8_t *buf, size_t len);
228 
229 /* console-dbus API */
230 void dbus_init(struct console *console,
231 	       struct config *config __attribute__((unused)));
232 
233 /* socket-handler API */
234 int dbus_create_socket_consumer(struct console *console);
235 
236 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
237 
238 #ifndef offsetof
239 #define offsetof(type, member) ((unsigned long)&((type *)NULL)->member)
240 #endif
241 
242 #define container_of(ptr, type, member)                                        \
243 	((type *)((void *)((ptr)-offsetof(type, member))))
244 
245 #define BUILD_ASSERT(c)                                                        \
246 	do {                                                                   \
247 		char __c[(c) ? 1 : -1] __attribute__((unused));                \
248 	} while (0)
249