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