xref: /openbmc/qemu/chardev/char-hmp-cmds.c (revision 579510e196a544b42bd8bca9cc61688d4d1211ac)
1*b7d75c0bSMarkus Armbruster /*
2*b7d75c0bSMarkus Armbruster  * HMP commands related to character devices
3*b7d75c0bSMarkus Armbruster  *
4*b7d75c0bSMarkus Armbruster  * Copyright IBM, Corp. 2011
5*b7d75c0bSMarkus Armbruster  *
6*b7d75c0bSMarkus Armbruster  * Authors:
7*b7d75c0bSMarkus Armbruster  *  Anthony Liguori   <aliguori@us.ibm.com>
8*b7d75c0bSMarkus Armbruster  *
9*b7d75c0bSMarkus Armbruster  * This work is licensed under the terms of the GNU GPL, version 2.  See
10*b7d75c0bSMarkus Armbruster  * the COPYING file in the top-level directory.
11*b7d75c0bSMarkus Armbruster  *
12*b7d75c0bSMarkus Armbruster  * Contributions after 2012-01-13 are licensed under the terms of the
13*b7d75c0bSMarkus Armbruster  * GNU GPL, version 2 or (at your option) any later version.
14*b7d75c0bSMarkus Armbruster  */
15*b7d75c0bSMarkus Armbruster 
16*b7d75c0bSMarkus Armbruster #include "qemu/osdep.h"
17*b7d75c0bSMarkus Armbruster #include "chardev/char.h"
18*b7d75c0bSMarkus Armbruster #include "monitor/hmp.h"
19*b7d75c0bSMarkus Armbruster #include "monitor/monitor.h"
20*b7d75c0bSMarkus Armbruster #include "qapi/error.h"
21*b7d75c0bSMarkus Armbruster #include "qapi/qapi-commands-char.h"
22*b7d75c0bSMarkus Armbruster #include "qapi/qmp/qdict.h"
23*b7d75c0bSMarkus Armbruster #include "qemu/config-file.h"
24*b7d75c0bSMarkus Armbruster #include "qemu/option.h"
25*b7d75c0bSMarkus Armbruster 
hmp_info_chardev(Monitor * mon,const QDict * qdict)26*b7d75c0bSMarkus Armbruster void hmp_info_chardev(Monitor *mon, const QDict *qdict)
27*b7d75c0bSMarkus Armbruster {
28*b7d75c0bSMarkus Armbruster     ChardevInfoList *char_info, *info;
29*b7d75c0bSMarkus Armbruster 
30*b7d75c0bSMarkus Armbruster     char_info = qmp_query_chardev(NULL);
31*b7d75c0bSMarkus Armbruster     for (info = char_info; info; info = info->next) {
32*b7d75c0bSMarkus Armbruster         monitor_printf(mon, "%s: filename=%s\n", info->value->label,
33*b7d75c0bSMarkus Armbruster                                                  info->value->filename);
34*b7d75c0bSMarkus Armbruster     }
35*b7d75c0bSMarkus Armbruster 
36*b7d75c0bSMarkus Armbruster     qapi_free_ChardevInfoList(char_info);
37*b7d75c0bSMarkus Armbruster }
38*b7d75c0bSMarkus Armbruster 
hmp_ringbuf_write(Monitor * mon,const QDict * qdict)39*b7d75c0bSMarkus Armbruster void hmp_ringbuf_write(Monitor *mon, const QDict *qdict)
40*b7d75c0bSMarkus Armbruster {
41*b7d75c0bSMarkus Armbruster     const char *chardev = qdict_get_str(qdict, "device");
42*b7d75c0bSMarkus Armbruster     const char *data = qdict_get_str(qdict, "data");
43*b7d75c0bSMarkus Armbruster     Error *err = NULL;
44*b7d75c0bSMarkus Armbruster 
45*b7d75c0bSMarkus Armbruster     qmp_ringbuf_write(chardev, data, false, 0, &err);
46*b7d75c0bSMarkus Armbruster 
47*b7d75c0bSMarkus Armbruster     hmp_handle_error(mon, err);
48*b7d75c0bSMarkus Armbruster }
49*b7d75c0bSMarkus Armbruster 
hmp_ringbuf_read(Monitor * mon,const QDict * qdict)50*b7d75c0bSMarkus Armbruster void hmp_ringbuf_read(Monitor *mon, const QDict *qdict)
51*b7d75c0bSMarkus Armbruster {
52*b7d75c0bSMarkus Armbruster     uint32_t size = qdict_get_int(qdict, "size");
53*b7d75c0bSMarkus Armbruster     const char *chardev = qdict_get_str(qdict, "device");
54*b7d75c0bSMarkus Armbruster     char *data;
55*b7d75c0bSMarkus Armbruster     Error *err = NULL;
56*b7d75c0bSMarkus Armbruster     int i;
57*b7d75c0bSMarkus Armbruster 
58*b7d75c0bSMarkus Armbruster     data = qmp_ringbuf_read(chardev, size, false, 0, &err);
59*b7d75c0bSMarkus Armbruster     if (hmp_handle_error(mon, err)) {
60*b7d75c0bSMarkus Armbruster         return;
61*b7d75c0bSMarkus Armbruster     }
62*b7d75c0bSMarkus Armbruster 
63*b7d75c0bSMarkus Armbruster     for (i = 0; data[i]; i++) {
64*b7d75c0bSMarkus Armbruster         unsigned char ch = data[i];
65*b7d75c0bSMarkus Armbruster 
66*b7d75c0bSMarkus Armbruster         if (ch == '\\') {
67*b7d75c0bSMarkus Armbruster             monitor_printf(mon, "\\\\");
68*b7d75c0bSMarkus Armbruster         } else if ((ch < 0x20 && ch != '\n' && ch != '\t') || ch == 0x7F) {
69*b7d75c0bSMarkus Armbruster             monitor_printf(mon, "\\u%04X", ch);
70*b7d75c0bSMarkus Armbruster         } else {
71*b7d75c0bSMarkus Armbruster             monitor_printf(mon, "%c", ch);
72*b7d75c0bSMarkus Armbruster         }
73*b7d75c0bSMarkus Armbruster 
74*b7d75c0bSMarkus Armbruster     }
75*b7d75c0bSMarkus Armbruster     monitor_printf(mon, "\n");
76*b7d75c0bSMarkus Armbruster     g_free(data);
77*b7d75c0bSMarkus Armbruster }
78*b7d75c0bSMarkus Armbruster 
hmp_chardev_add(Monitor * mon,const QDict * qdict)79*b7d75c0bSMarkus Armbruster void hmp_chardev_add(Monitor *mon, const QDict *qdict)
80*b7d75c0bSMarkus Armbruster {
81*b7d75c0bSMarkus Armbruster     const char *args = qdict_get_str(qdict, "args");
82*b7d75c0bSMarkus Armbruster     Error *err = NULL;
83*b7d75c0bSMarkus Armbruster     QemuOpts *opts;
84*b7d75c0bSMarkus Armbruster 
85*b7d75c0bSMarkus Armbruster     opts = qemu_opts_parse_noisily(qemu_find_opts("chardev"), args, true);
86*b7d75c0bSMarkus Armbruster     if (opts == NULL) {
87*b7d75c0bSMarkus Armbruster         error_setg(&err, "Parsing chardev args failed");
88*b7d75c0bSMarkus Armbruster     } else {
89*b7d75c0bSMarkus Armbruster         qemu_chr_new_from_opts(opts, NULL, &err);
90*b7d75c0bSMarkus Armbruster         qemu_opts_del(opts);
91*b7d75c0bSMarkus Armbruster     }
92*b7d75c0bSMarkus Armbruster     hmp_handle_error(mon, err);
93*b7d75c0bSMarkus Armbruster }
94*b7d75c0bSMarkus Armbruster 
hmp_chardev_change(Monitor * mon,const QDict * qdict)95*b7d75c0bSMarkus Armbruster void hmp_chardev_change(Monitor *mon, const QDict *qdict)
96*b7d75c0bSMarkus Armbruster {
97*b7d75c0bSMarkus Armbruster     const char *args = qdict_get_str(qdict, "args");
98*b7d75c0bSMarkus Armbruster     const char *id;
99*b7d75c0bSMarkus Armbruster     Error *err = NULL;
100*b7d75c0bSMarkus Armbruster     ChardevBackend *backend = NULL;
101*b7d75c0bSMarkus Armbruster     ChardevReturn *ret = NULL;
102*b7d75c0bSMarkus Armbruster     QemuOpts *opts = qemu_opts_parse_noisily(qemu_find_opts("chardev"), args,
103*b7d75c0bSMarkus Armbruster                                              true);
104*b7d75c0bSMarkus Armbruster     if (!opts) {
105*b7d75c0bSMarkus Armbruster         error_setg(&err, "Parsing chardev args failed");
106*b7d75c0bSMarkus Armbruster         goto end;
107*b7d75c0bSMarkus Armbruster     }
108*b7d75c0bSMarkus Armbruster 
109*b7d75c0bSMarkus Armbruster     id = qdict_get_str(qdict, "id");
110*b7d75c0bSMarkus Armbruster     if (qemu_opts_id(opts)) {
111*b7d75c0bSMarkus Armbruster         error_setg(&err, "Unexpected 'id' parameter");
112*b7d75c0bSMarkus Armbruster         goto end;
113*b7d75c0bSMarkus Armbruster     }
114*b7d75c0bSMarkus Armbruster 
115*b7d75c0bSMarkus Armbruster     backend = qemu_chr_parse_opts(opts, &err);
116*b7d75c0bSMarkus Armbruster     if (!backend) {
117*b7d75c0bSMarkus Armbruster         goto end;
118*b7d75c0bSMarkus Armbruster     }
119*b7d75c0bSMarkus Armbruster 
120*b7d75c0bSMarkus Armbruster     ret = qmp_chardev_change(id, backend, &err);
121*b7d75c0bSMarkus Armbruster 
122*b7d75c0bSMarkus Armbruster end:
123*b7d75c0bSMarkus Armbruster     qapi_free_ChardevReturn(ret);
124*b7d75c0bSMarkus Armbruster     qapi_free_ChardevBackend(backend);
125*b7d75c0bSMarkus Armbruster     qemu_opts_del(opts);
126*b7d75c0bSMarkus Armbruster     hmp_handle_error(mon, err);
127*b7d75c0bSMarkus Armbruster }
128*b7d75c0bSMarkus Armbruster 
hmp_chardev_remove(Monitor * mon,const QDict * qdict)129*b7d75c0bSMarkus Armbruster void hmp_chardev_remove(Monitor *mon, const QDict *qdict)
130*b7d75c0bSMarkus Armbruster {
131*b7d75c0bSMarkus Armbruster     Error *local_err = NULL;
132*b7d75c0bSMarkus Armbruster 
133*b7d75c0bSMarkus Armbruster     qmp_chardev_remove(qdict_get_str(qdict, "id"), &local_err);
134*b7d75c0bSMarkus Armbruster     hmp_handle_error(mon, local_err);
135*b7d75c0bSMarkus Armbruster }
136*b7d75c0bSMarkus Armbruster 
hmp_chardev_send_break(Monitor * mon,const QDict * qdict)137*b7d75c0bSMarkus Armbruster void hmp_chardev_send_break(Monitor *mon, const QDict *qdict)
138*b7d75c0bSMarkus Armbruster {
139*b7d75c0bSMarkus Armbruster     Error *local_err = NULL;
140*b7d75c0bSMarkus Armbruster 
141*b7d75c0bSMarkus Armbruster     qmp_chardev_send_break(qdict_get_str(qdict, "id"), &local_err);
142*b7d75c0bSMarkus Armbruster     hmp_handle_error(mon, local_err);
143*b7d75c0bSMarkus Armbruster }
144*b7d75c0bSMarkus Armbruster 
chardev_add_completion(ReadLineState * rs,int nb_args,const char * str)145*b7d75c0bSMarkus Armbruster void chardev_add_completion(ReadLineState *rs, int nb_args, const char *str)
146*b7d75c0bSMarkus Armbruster {
147*b7d75c0bSMarkus Armbruster     size_t len;
148*b7d75c0bSMarkus Armbruster     ChardevBackendInfoList *list, *start;
149*b7d75c0bSMarkus Armbruster 
150*b7d75c0bSMarkus Armbruster     if (nb_args != 2) {
151*b7d75c0bSMarkus Armbruster         return;
152*b7d75c0bSMarkus Armbruster     }
153*b7d75c0bSMarkus Armbruster     len = strlen(str);
154*b7d75c0bSMarkus Armbruster     readline_set_completion_index(rs, len);
155*b7d75c0bSMarkus Armbruster 
156*b7d75c0bSMarkus Armbruster     start = list = qmp_query_chardev_backends(NULL);
157*b7d75c0bSMarkus Armbruster     while (list) {
158*b7d75c0bSMarkus Armbruster         const char *chr_name = list->value->name;
159*b7d75c0bSMarkus Armbruster 
160*b7d75c0bSMarkus Armbruster         if (!strncmp(chr_name, str, len)) {
161*b7d75c0bSMarkus Armbruster             readline_add_completion(rs, chr_name);
162*b7d75c0bSMarkus Armbruster         }
163*b7d75c0bSMarkus Armbruster         list = list->next;
164*b7d75c0bSMarkus Armbruster     }
165*b7d75c0bSMarkus Armbruster     qapi_free_ChardevBackendInfoList(start);
166*b7d75c0bSMarkus Armbruster }
167*b7d75c0bSMarkus Armbruster 
chardev_remove_completion(ReadLineState * rs,int nb_args,const char * str)168*b7d75c0bSMarkus Armbruster void chardev_remove_completion(ReadLineState *rs, int nb_args, const char *str)
169*b7d75c0bSMarkus Armbruster {
170*b7d75c0bSMarkus Armbruster     size_t len;
171*b7d75c0bSMarkus Armbruster     ChardevInfoList *list, *start;
172*b7d75c0bSMarkus Armbruster 
173*b7d75c0bSMarkus Armbruster     if (nb_args != 2) {
174*b7d75c0bSMarkus Armbruster         return;
175*b7d75c0bSMarkus Armbruster     }
176*b7d75c0bSMarkus Armbruster     len = strlen(str);
177*b7d75c0bSMarkus Armbruster     readline_set_completion_index(rs, len);
178*b7d75c0bSMarkus Armbruster 
179*b7d75c0bSMarkus Armbruster     start = list = qmp_query_chardev(NULL);
180*b7d75c0bSMarkus Armbruster     while (list) {
181*b7d75c0bSMarkus Armbruster         ChardevInfo *chr = list->value;
182*b7d75c0bSMarkus Armbruster 
183*b7d75c0bSMarkus Armbruster         if (!strncmp(chr->label, str, len)) {
184*b7d75c0bSMarkus Armbruster             readline_add_completion(rs, chr->label);
185*b7d75c0bSMarkus Armbruster         }
186*b7d75c0bSMarkus Armbruster         list = list->next;
187*b7d75c0bSMarkus Armbruster     }
188*b7d75c0bSMarkus Armbruster     qapi_free_ChardevInfoList(start);
189*b7d75c0bSMarkus Armbruster }
190*b7d75c0bSMarkus Armbruster 
ringbuf_completion(ReadLineState * rs,const char * str)191*b7d75c0bSMarkus Armbruster static void ringbuf_completion(ReadLineState *rs, const char *str)
192*b7d75c0bSMarkus Armbruster {
193*b7d75c0bSMarkus Armbruster     size_t len;
194*b7d75c0bSMarkus Armbruster     ChardevInfoList *list, *start;
195*b7d75c0bSMarkus Armbruster 
196*b7d75c0bSMarkus Armbruster     len = strlen(str);
197*b7d75c0bSMarkus Armbruster     readline_set_completion_index(rs, len);
198*b7d75c0bSMarkus Armbruster 
199*b7d75c0bSMarkus Armbruster     start = list = qmp_query_chardev(NULL);
200*b7d75c0bSMarkus Armbruster     while (list) {
201*b7d75c0bSMarkus Armbruster         ChardevInfo *chr_info = list->value;
202*b7d75c0bSMarkus Armbruster 
203*b7d75c0bSMarkus Armbruster         if (!strncmp(chr_info->label, str, len)) {
204*b7d75c0bSMarkus Armbruster             Chardev *chr = qemu_chr_find(chr_info->label);
205*b7d75c0bSMarkus Armbruster             if (chr && CHARDEV_IS_RINGBUF(chr)) {
206*b7d75c0bSMarkus Armbruster                 readline_add_completion(rs, chr_info->label);
207*b7d75c0bSMarkus Armbruster             }
208*b7d75c0bSMarkus Armbruster         }
209*b7d75c0bSMarkus Armbruster         list = list->next;
210*b7d75c0bSMarkus Armbruster     }
211*b7d75c0bSMarkus Armbruster     qapi_free_ChardevInfoList(start);
212*b7d75c0bSMarkus Armbruster }
213*b7d75c0bSMarkus Armbruster 
ringbuf_write_completion(ReadLineState * rs,int nb_args,const char * str)214*b7d75c0bSMarkus Armbruster void ringbuf_write_completion(ReadLineState *rs, int nb_args, const char *str)
215*b7d75c0bSMarkus Armbruster {
216*b7d75c0bSMarkus Armbruster     if (nb_args != 2) {
217*b7d75c0bSMarkus Armbruster         return;
218*b7d75c0bSMarkus Armbruster     }
219*b7d75c0bSMarkus Armbruster     ringbuf_completion(rs, str);
220*b7d75c0bSMarkus Armbruster }
221