1 /* 2 * SCLP event types 3 * Operations Command - Line Mode input 4 * Message - Line Mode output 5 * 6 * Copyright IBM, Corp. 2013 7 * 8 * Authors: 9 * Heinz Graalfs <graalfs@linux.vnet.ibm.com> 10 * 11 * This work is licensed under the terms of the GNU GPL, version 2 or (at your 12 * option) any later version. See the COPYING file in the top-level directory. 13 * 14 */ 15 16 #include "qemu/osdep.h" 17 #include "hw/qdev.h" 18 #include "qemu/thread.h" 19 #include "qemu/error-report.h" 20 #include "chardev/char-fe.h" 21 22 #include "hw/s390x/sclp.h" 23 #include "hw/s390x/event-facility.h" 24 #include "hw/s390x/ebcdic.h" 25 26 #define SIZE_BUFFER 4096 27 #define NEWLINE "\n" 28 29 typedef struct OprtnsCommand { 30 EventBufferHeader header; 31 MDMSU message_unit; 32 char data[0]; 33 } QEMU_PACKED OprtnsCommand; 34 35 /* max size for line-mode data in 4K SCCB page */ 36 #define SIZE_CONSOLE_BUFFER (SCCB_DATA_LEN - sizeof(OprtnsCommand)) 37 38 typedef struct SCLPConsoleLM { 39 SCLPEvent event; 40 CharBackend chr; 41 bool echo; /* immediate echo of input if true */ 42 uint32_t write_errors; /* errors writing to char layer */ 43 uint32_t length; /* length of byte stream in buffer */ 44 uint8_t buf[SIZE_CONSOLE_BUFFER]; 45 } SCLPConsoleLM; 46 47 #define TYPE_SCLPLM_CONSOLE "sclplmconsole" 48 #define SCLPLM_CONSOLE(obj) \ 49 OBJECT_CHECK(SCLPConsoleLM, (obj), TYPE_SCLPLM_CONSOLE) 50 51 /* 52 * Character layer call-back functions 53 * 54 * Allow 1 character at a time 55 * 56 * Accumulate bytes from character layer in console buffer, 57 * event_pending is set when a newline character is encountered 58 * 59 * The maximum command line length is limited by the maximum 60 * space available in an SCCB. Line mode console input is sent 61 * truncated to the guest in case it doesn't fit into the SCCB. 62 */ 63 64 static int chr_can_read(void *opaque) 65 { 66 SCLPConsoleLM *scon = opaque; 67 68 if (scon->event.event_pending) { 69 return 0; 70 } 71 return 1; 72 } 73 74 static void chr_read(void *opaque, const uint8_t *buf, int size) 75 { 76 SCLPConsoleLM *scon = opaque; 77 78 assert(size == 1); 79 80 if (*buf == '\r' || *buf == '\n') { 81 scon->event.event_pending = true; 82 sclp_service_interrupt(0); 83 return; 84 } 85 if (scon->length == SIZE_CONSOLE_BUFFER) { 86 /* Eat the character, but still process CR and LF. */ 87 return; 88 } 89 scon->buf[scon->length] = *buf; 90 scon->length += 1; 91 if (scon->echo) { 92 /* XXX this blocks entire thread. Rewrite to use 93 * qemu_chr_fe_write and background I/O callbacks */ 94 qemu_chr_fe_write_all(&scon->chr, buf, size); 95 } 96 } 97 98 /* functions to be called by event facility */ 99 100 static bool can_handle_event(uint8_t type) 101 { 102 return type == SCLP_EVENT_MESSAGE || type == SCLP_EVENT_PMSGCMD; 103 } 104 105 static unsigned int send_mask(void) 106 { 107 return SCLP_EVENT_MASK_OP_CMD | SCLP_EVENT_MASK_PMSGCMD; 108 } 109 110 static unsigned int receive_mask(void) 111 { 112 return SCLP_EVENT_MASK_MSG | SCLP_EVENT_MASK_PMSGCMD; 113 } 114 115 /* 116 * Triggered by SCLP's read_event_data 117 * - convert ASCII byte stream to EBCDIC and 118 * - copy converted data into provided (SCLP) buffer 119 */ 120 static int get_console_data(SCLPEvent *event, uint8_t *buf, size_t *size, 121 int avail) 122 { 123 int len; 124 125 SCLPConsoleLM *cons = SCLPLM_CONSOLE(event); 126 127 len = cons->length; 128 /* data need to fit into provided SCLP buffer */ 129 if (len > avail) { 130 return 1; 131 } 132 133 ebcdic_put(buf, (char *)&cons->buf, len); 134 *size = len; 135 cons->length = 0; 136 /* data provided and no more data pending */ 137 event->event_pending = false; 138 qemu_notify_event(); 139 return 0; 140 } 141 142 static int read_event_data(SCLPEvent *event, EventBufferHeader *evt_buf_hdr, 143 int *slen) 144 { 145 int avail, rc; 146 size_t src_len; 147 uint8_t *to; 148 OprtnsCommand *oc = (OprtnsCommand *) evt_buf_hdr; 149 150 if (!event->event_pending) { 151 /* no data pending */ 152 return 0; 153 } 154 155 to = (uint8_t *)&oc->data; 156 avail = *slen - sizeof(OprtnsCommand); 157 rc = get_console_data(event, to, &src_len, avail); 158 if (rc) { 159 /* data didn't fit, try next SCCB */ 160 return 1; 161 } 162 163 oc->message_unit.mdmsu.gds_id = GDS_ID_MDSMU; 164 oc->message_unit.mdmsu.length = cpu_to_be16(sizeof(struct MDMSU)); 165 166 oc->message_unit.cpmsu.gds_id = GDS_ID_CPMSU; 167 oc->message_unit.cpmsu.length = 168 cpu_to_be16(sizeof(struct MDMSU) - sizeof(GdsVector)); 169 170 oc->message_unit.text_command.gds_id = GDS_ID_TEXTCMD; 171 oc->message_unit.text_command.length = 172 cpu_to_be16(sizeof(struct MDMSU) - (2 * sizeof(GdsVector))); 173 174 oc->message_unit.self_def_text_message.key = GDS_KEY_SELFDEFTEXTMSG; 175 oc->message_unit.self_def_text_message.length = 176 cpu_to_be16(sizeof(struct MDMSU) - (3 * sizeof(GdsVector))); 177 178 oc->message_unit.text_message.key = GDS_KEY_TEXTMSG; 179 oc->message_unit.text_message.length = 180 cpu_to_be16(sizeof(GdsSubvector) + src_len); 181 182 oc->header.length = cpu_to_be16(sizeof(OprtnsCommand) + src_len); 183 oc->header.type = SCLP_EVENT_OPRTNS_COMMAND; 184 *slen = avail - src_len; 185 186 return 1; 187 } 188 189 /* 190 * Triggered by SCLP's write_event_data 191 * - write console data to character layer 192 * returns < 0 if an error occurred 193 */ 194 static int write_console_data(SCLPEvent *event, const uint8_t *buf, int len) 195 { 196 SCLPConsoleLM *scon = SCLPLM_CONSOLE(event); 197 198 if (!qemu_chr_fe_backend_connected(&scon->chr)) { 199 /* If there's no backend, we can just say we consumed all data. */ 200 return len; 201 } 202 203 /* XXX this blocks entire thread. Rewrite to use 204 * qemu_chr_fe_write and background I/O callbacks */ 205 return qemu_chr_fe_write_all(&scon->chr, buf, len); 206 } 207 208 static int process_mdb(SCLPEvent *event, MDBO *mdbo) 209 { 210 int rc; 211 int len; 212 uint8_t buffer[SIZE_BUFFER]; 213 214 len = be16_to_cpu(mdbo->length); 215 len -= sizeof(mdbo->length) + sizeof(mdbo->type) 216 + sizeof(mdbo->mto.line_type_flags) 217 + sizeof(mdbo->mto.alarm_control) 218 + sizeof(mdbo->mto._reserved); 219 220 assert(len <= SIZE_BUFFER); 221 222 /* convert EBCDIC SCLP contents to ASCII console message */ 223 ascii_put(buffer, mdbo->mto.message, len); 224 rc = write_console_data(event, (uint8_t *)NEWLINE, 1); 225 if (rc < 0) { 226 return rc; 227 } 228 return write_console_data(event, buffer, len); 229 } 230 231 static int write_event_data(SCLPEvent *event, EventBufferHeader *ebh) 232 { 233 int len; 234 int written; 235 int errors = 0; 236 MDBO *mdbo; 237 SclpMsg *data = (SclpMsg *) ebh; 238 SCLPConsoleLM *scon = SCLPLM_CONSOLE(event); 239 240 len = be16_to_cpu(data->mdb.header.length); 241 if (len < sizeof(data->mdb.header)) { 242 return SCLP_RC_INCONSISTENT_LENGTHS; 243 } 244 len -= sizeof(data->mdb.header); 245 246 /* first check message buffers */ 247 mdbo = data->mdb.mdbo; 248 while (len > 0) { 249 if (be16_to_cpu(mdbo->length) > len 250 || be16_to_cpu(mdbo->length) == 0) { 251 return SCLP_RC_INCONSISTENT_LENGTHS; 252 } 253 len -= be16_to_cpu(mdbo->length); 254 mdbo = (void *) mdbo + be16_to_cpu(mdbo->length); 255 } 256 257 /* then execute */ 258 len = be16_to_cpu(data->mdb.header.length) - sizeof(data->mdb.header); 259 mdbo = data->mdb.mdbo; 260 while (len > 0) { 261 switch (be16_to_cpu(mdbo->type)) { 262 case MESSAGE_TEXT: 263 /* message text object */ 264 written = process_mdb(event, mdbo); 265 if (written < 0) { 266 /* character layer error */ 267 errors++; 268 } 269 break; 270 default: /* ignore */ 271 break; 272 } 273 len -= be16_to_cpu(mdbo->length); 274 mdbo = (void *) mdbo + be16_to_cpu(mdbo->length); 275 } 276 if (errors) { 277 scon->write_errors += errors; 278 } 279 data->header.flags = SCLP_EVENT_BUFFER_ACCEPTED; 280 281 return SCLP_RC_NORMAL_COMPLETION; 282 } 283 284 /* functions for live migration */ 285 286 static const VMStateDescription vmstate_sclplmconsole = { 287 .name = "sclplmconsole", 288 .version_id = 0, 289 .minimum_version_id = 0, 290 .fields = (VMStateField[]) { 291 VMSTATE_BOOL(event.event_pending, SCLPConsoleLM), 292 VMSTATE_UINT32(write_errors, SCLPConsoleLM), 293 VMSTATE_UINT32(length, SCLPConsoleLM), 294 VMSTATE_UINT8_ARRAY(buf, SCLPConsoleLM, SIZE_CONSOLE_BUFFER), 295 VMSTATE_END_OF_LIST() 296 } 297 }; 298 299 /* qemu object creation and initialization functions */ 300 301 /* tell character layer our call-back functions */ 302 303 static int console_init(SCLPEvent *event) 304 { 305 static bool console_available; 306 307 SCLPConsoleLM *scon = SCLPLM_CONSOLE(event); 308 309 if (console_available) { 310 error_report("Multiple line-mode operator consoles are not supported"); 311 return -1; 312 } 313 console_available = true; 314 315 qemu_chr_fe_set_handlers(&scon->chr, chr_can_read, 316 chr_read, NULL, NULL, scon, NULL, true); 317 318 return 0; 319 } 320 321 static int console_exit(SCLPEvent *event) 322 { 323 return 0; 324 } 325 326 static void console_reset(DeviceState *dev) 327 { 328 SCLPEvent *event = SCLP_EVENT(dev); 329 SCLPConsoleLM *scon = SCLPLM_CONSOLE(event); 330 331 event->event_pending = false; 332 scon->length = 0; 333 scon->write_errors = 0; 334 } 335 336 static Property console_properties[] = { 337 DEFINE_PROP_CHR("chardev", SCLPConsoleLM, chr), 338 DEFINE_PROP_UINT32("write_errors", SCLPConsoleLM, write_errors, 0), 339 DEFINE_PROP_BOOL("echo", SCLPConsoleLM, echo, true), 340 DEFINE_PROP_END_OF_LIST(), 341 }; 342 343 static void console_class_init(ObjectClass *klass, void *data) 344 { 345 DeviceClass *dc = DEVICE_CLASS(klass); 346 SCLPEventClass *ec = SCLP_EVENT_CLASS(klass); 347 348 dc->props = console_properties; 349 dc->reset = console_reset; 350 dc->vmsd = &vmstate_sclplmconsole; 351 ec->init = console_init; 352 ec->exit = console_exit; 353 ec->get_send_mask = send_mask; 354 ec->get_receive_mask = receive_mask; 355 ec->can_handle_event = can_handle_event; 356 ec->read_event_data = read_event_data; 357 ec->write_event_data = write_event_data; 358 set_bit(DEVICE_CATEGORY_INPUT, dc->categories); 359 } 360 361 static const TypeInfo sclp_console_info = { 362 .name = "sclplmconsole", 363 .parent = TYPE_SCLP_EVENT, 364 .instance_size = sizeof(SCLPConsoleLM), 365 .class_init = console_class_init, 366 .class_size = sizeof(SCLPEventClass), 367 }; 368 369 static void register_types(void) 370 { 371 type_register_static(&sclp_console_info); 372 } 373 374 type_init(register_types) 375