blob: d4477c172220d53018c3fad940591a0ba2362b17 [file] [log] [blame]
Ninad Palsulee258e512023-04-26 22:17:57 -05001/**
2 * Copyright © 2023 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
Andrew Jeffery30ea6382023-05-03 16:56:10 +093017#include <assert.h>
Ninad Palsulee258e512023-04-26 22:17:57 -050018#include <errno.h>
19#include <err.h>
Ninad Palsulebd992c92023-05-09 18:30:01 -050020#include <string.h>
21#include <sys/socket.h>
Ninad Palsulee258e512023-04-26 22:17:57 -050022
23#include "console-server.h"
24
25/* size of the dbus object path length */
26const size_t dbus_obj_path_len = 1024;
27
Ninad Palsuleb14ca192023-03-31 09:49:00 -050028#define DBUS_ERR "org.openbmc.error"
29#define DBUS_NAME "xyz.openbmc_project.Console.%s"
30#define OBJ_NAME "/xyz/openbmc_project/console/%s"
31#define TTY_INTF "xyz.openbmc_project.console"
32#define ACCESS_INTF "xyz.openbmc_project.Console.Access"
Ninad Palsulee258e512023-04-26 22:17:57 -050033
34static void tty_change_baudrate(struct console *console)
35{
36 struct handler *handler;
37 int i;
38 int rc;
39
40 tty_init_termios(console);
41
42 for (i = 0; i < console->n_handlers; i++) {
43 handler = console->handlers[i];
44 if (!handler->baudrate) {
45 continue;
46 }
47
Andrew Jeffery30ea6382023-05-03 16:56:10 +093048 rc = handler->baudrate(handler, console->tty.uart.baud);
Ninad Palsulee258e512023-04-26 22:17:57 -050049 if (rc) {
50 warnx("Can't set terminal baudrate for handler %s",
51 handler->name);
52 }
53 }
54}
55
56static int method_set_baud_rate(sd_bus_message *msg, void *userdata,
57 sd_bus_error *err)
58{
59 struct console *console = userdata;
60 uint32_t baudrate;
61 speed_t speed;
62 int r;
63
64 if (!console) {
65 sd_bus_error_set_const(err, DBUS_ERR, "Internal error");
66 return sd_bus_reply_method_return(msg, "x", 0);
67 }
68
69 r = sd_bus_message_read(msg, "u", &baudrate);
70 if (r < 0) {
71 sd_bus_error_set_const(err, DBUS_ERR, "Bad message");
72 return sd_bus_reply_method_return(msg, "x", -EINVAL);
73 }
74
75 speed = parse_int_to_baud(baudrate);
76 if (!speed) {
77 warnx("Invalid baud rate: '%u'", baudrate);
78 return sd_bus_reply_method_return(msg, "x", -EINVAL);
79 }
80
Andrew Jeffery30ea6382023-05-03 16:56:10 +093081 assert(console->tty.type == TTY_DEVICE_UART);
82 console->tty.uart.baud = speed;
Ninad Palsulee258e512023-04-26 22:17:57 -050083 tty_change_baudrate(console);
84
85 return sd_bus_reply_method_return(msg, "x", r);
86}
87
88static int get_handler(sd_bus *bus __attribute__((unused)),
89 const char *path __attribute__((unused)),
90 const char *interface __attribute__((unused)),
91 const char *property __attribute__((unused)),
92 sd_bus_message *reply, void *userdata,
93 sd_bus_error *error __attribute__((unused)))
94{
95 struct console *console = userdata;
96 uint32_t baudrate;
97 int r;
98
Andrew Jeffery30ea6382023-05-03 16:56:10 +093099 assert(console->tty.type == TTY_DEVICE_UART);
100 baudrate = parse_baud_to_int(console->tty.uart.baud);
Ninad Palsulee258e512023-04-26 22:17:57 -0500101 if (!baudrate) {
Andrew Jeffery30ea6382023-05-03 16:56:10 +0930102 warnx("Invalid baud rate: '%d'", console->tty.uart.baud);
Ninad Palsulee258e512023-04-26 22:17:57 -0500103 }
104
105 r = sd_bus_message_append(reply, "u", baudrate);
106
107 return r;
108}
109
Ninad Palsulebd992c92023-05-09 18:30:01 -0500110static int method_connect(sd_bus_message *msg, void *userdata,
111 sd_bus_error *err)
Ninad Palsuleb14ca192023-03-31 09:49:00 -0500112{
113 struct console *console = userdata;
Ninad Palsulebd992c92023-05-09 18:30:01 -0500114 int rc;
115 int socket_fd = -1;
Ninad Palsuleb14ca192023-03-31 09:49:00 -0500116
Ninad Palsulebd992c92023-05-09 18:30:01 -0500117 if (!console) {
118 warnx("Internal error: Console pointer is null");
119 sd_bus_error_set_const(err, DBUS_ERR, "Internal error");
120 return sd_bus_reply_method_error(msg, err);
121 }
122
123 /* Register the consumer. */
124 socket_fd = dbus_create_socket_consumer(console);
125 if (socket_fd < 0) {
126 rc = socket_fd;
127 warnx("Failed to create socket consumer: %s", strerror(rc));
128 sd_bus_error_set_const(err, DBUS_ERR,
129 "Failed to create socket consumer");
130 return sd_bus_reply_method_error(msg, err);
131 }
132
133 rc = sd_bus_reply_method_return(msg, "h", socket_fd);
134
135 /* Close the our end */
136 close(socket_fd);
137
138 return rc;
Ninad Palsuleb14ca192023-03-31 09:49:00 -0500139}
140
141static const sd_bus_vtable console_tty_vtable[] = {
Ninad Palsulee258e512023-04-26 22:17:57 -0500142 SD_BUS_VTABLE_START(0),
143 SD_BUS_METHOD("setBaudRate", "u", "x", method_set_baud_rate,
144 SD_BUS_VTABLE_UNPRIVILEGED),
145 SD_BUS_PROPERTY("baudrate", "u", get_handler, 0, 0),
146 SD_BUS_VTABLE_END,
147};
148
Ninad Palsuleb14ca192023-03-31 09:49:00 -0500149static const sd_bus_vtable console_access_vtable[] = {
150 SD_BUS_VTABLE_START(0),
Ninad Palsulebd992c92023-05-09 18:30:01 -0500151 SD_BUS_METHOD("Connect", SD_BUS_NO_ARGS, "h", method_connect,
152 SD_BUS_VTABLE_UNPRIVILEGED),
Ninad Palsuleb14ca192023-03-31 09:49:00 -0500153 SD_BUS_VTABLE_END,
154};
155
Ninad Palsulee258e512023-04-26 22:17:57 -0500156void dbus_init(struct console *console,
157 struct config *config __attribute__((unused)))
158{
159 char obj_name[dbus_obj_path_len];
160 char dbus_name[dbus_obj_path_len];
161 int dbus_poller = 0;
162 int fd;
163 int r;
164 size_t bytes;
165
166 if (!console) {
167 warnx("Couldn't get valid console");
168 return;
169 }
170
171 r = sd_bus_default_system(&console->bus);
172 if (r < 0) {
173 warnx("Failed to connect to system bus: %s", strerror(-r));
174 return;
175 }
176
177 /* Register support console interface */
178 bytes = snprintf(obj_name, dbus_obj_path_len, OBJ_NAME,
179 console->console_id);
180 if (bytes >= dbus_obj_path_len) {
181 warnx("Console id '%s' is too long. There is no enough space in the buffer.",
182 console->console_id);
183 return;
184 }
185
Andrew Jeffery30ea6382023-05-03 16:56:10 +0930186 if (console->tty.type == TTY_DEVICE_UART) {
187 /* Register tty interface */
188 r = sd_bus_add_object_vtable(console->bus, NULL, obj_name,
189 TTY_INTF, console_tty_vtable,
190 console);
191 if (r < 0) {
192 warnx("Failed to issue method call: %s", strerror(-r));
193 return;
194 }
Ninad Palsuleb14ca192023-03-31 09:49:00 -0500195 }
196
197 /* Register access interface */
198 r = sd_bus_add_object_vtable(console->bus, NULL, obj_name, ACCESS_INTF,
199 console_access_vtable, console);
Ninad Palsulee258e512023-04-26 22:17:57 -0500200 if (r < 0) {
201 warnx("Failed to issue method call: %s", strerror(-r));
202 return;
203 }
204
205 bytes = snprintf(dbus_name, dbus_obj_path_len, DBUS_NAME,
206 console->console_id);
207 if (bytes >= dbus_obj_path_len) {
208 warnx("Console id '%s' is too long. There is no enough space in the buffer.",
209 console->console_id);
210 return;
211 }
212
Ninad Palsuleb14ca192023-03-31 09:49:00 -0500213 /* Finally register the bus name */
Ninad Palsulee258e512023-04-26 22:17:57 -0500214 r = sd_bus_request_name(console->bus, dbus_name,
215 SD_BUS_NAME_ALLOW_REPLACEMENT |
216 SD_BUS_NAME_REPLACE_EXISTING);
217 if (r < 0) {
218 warnx("Failed to acquire service name: %s", strerror(-r));
219 return;
220 }
221
222 fd = sd_bus_get_fd(console->bus);
223 if (fd < 0) {
224 warnx("Couldn't get the bus file descriptor");
225 return;
226 }
227
228 dbus_poller = POLLFD_DBUS;
229
230 console->pollfds[dbus_poller].fd = fd;
231 console->pollfds[dbus_poller].events = POLLIN;
232}