cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

char-serial.c (8592B)


      1/*
      2 * QEMU System Emulator
      3 *
      4 * Copyright (c) 2003-2008 Fabrice Bellard
      5 *
      6 * Permission is hereby granted, free of charge, to any person obtaining a copy
      7 * of this software and associated documentation files (the "Software"), to deal
      8 * in the Software without restriction, including without limitation the rights
      9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     10 * copies of the Software, and to permit persons to whom the Software is
     11 * furnished to do so, subject to the following conditions:
     12 *
     13 * The above copyright notice and this permission notice shall be included in
     14 * all copies or substantial portions of the Software.
     15 *
     16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
     19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     22 * THE SOFTWARE.
     23 */
     24
     25#include "qemu/osdep.h"
     26#include "qemu/module.h"
     27#include "qemu/option.h"
     28#include "qemu/sockets.h"
     29#include "io/channel-file.h"
     30#include "qapi/error.h"
     31
     32#ifdef _WIN32
     33#include "chardev/char-win.h"
     34#else
     35#include <sys/ioctl.h>
     36#include <termios.h>
     37#include "chardev/char-fd.h"
     38#endif
     39
     40#include "chardev/char-serial.h"
     41
     42#ifdef _WIN32
     43
     44static void qmp_chardev_open_serial(Chardev *chr,
     45                                    ChardevBackend *backend,
     46                                    bool *be_opened,
     47                                    Error **errp)
     48{
     49    ChardevHostdev *serial = backend->u.serial.data;
     50
     51    win_chr_serial_init(chr, serial->device, errp);
     52}
     53
     54#elif defined(__linux__) || defined(__sun__) || defined(__FreeBSD__)      \
     55    || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) \
     56    || defined(__GLIBC__) || defined(__APPLE__)
     57
     58static void tty_serial_init(int fd, int speed,
     59                            int parity, int data_bits, int stop_bits)
     60{
     61    struct termios tty = {0};
     62    speed_t spd;
     63
     64#if 0
     65    printf("tty_serial_init: speed=%d parity=%c data=%d stop=%d\n",
     66           speed, parity, data_bits, stop_bits);
     67#endif
     68    tcgetattr(fd, &tty);
     69
     70#define check_speed(val) \
     71    if (speed <= val) {  \
     72        spd = B##val;    \
     73        goto done;       \
     74    }
     75
     76    speed = speed * 10 / 11;
     77    check_speed(50);
     78    check_speed(75);
     79    check_speed(110);
     80    check_speed(134);
     81    check_speed(150);
     82    check_speed(200);
     83    check_speed(300);
     84    check_speed(600);
     85    check_speed(1200);
     86    check_speed(1800);
     87    check_speed(2400);
     88    check_speed(4800);
     89    check_speed(9600);
     90    check_speed(19200);
     91    check_speed(38400);
     92    /* Non-Posix values follow. They may be unsupported on some systems. */
     93    check_speed(57600);
     94    check_speed(115200);
     95#ifdef B230400
     96    check_speed(230400);
     97#endif
     98#ifdef B460800
     99    check_speed(460800);
    100#endif
    101#ifdef B500000
    102    check_speed(500000);
    103#endif
    104#ifdef B576000
    105    check_speed(576000);
    106#endif
    107#ifdef B921600
    108    check_speed(921600);
    109#endif
    110#ifdef B1000000
    111    check_speed(1000000);
    112#endif
    113#ifdef B1152000
    114    check_speed(1152000);
    115#endif
    116#ifdef B1500000
    117    check_speed(1500000);
    118#endif
    119#ifdef B2000000
    120    check_speed(2000000);
    121#endif
    122#ifdef B2500000
    123    check_speed(2500000);
    124#endif
    125#ifdef B3000000
    126    check_speed(3000000);
    127#endif
    128#ifdef B3500000
    129    check_speed(3500000);
    130#endif
    131#ifdef B4000000
    132    check_speed(4000000);
    133#endif
    134    spd = B115200;
    135
    136#undef check_speed
    137 done:
    138    cfsetispeed(&tty, spd);
    139    cfsetospeed(&tty, spd);
    140
    141    tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
    142                     | INLCR | IGNCR | ICRNL | IXON);
    143    tty.c_oflag &= ~OPOST;
    144    tty.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN | ISIG);
    145    tty.c_cflag &= ~(CSIZE | PARENB | PARODD | CRTSCTS | CSTOPB);
    146    switch (data_bits) {
    147    default:
    148    case 8:
    149        tty.c_cflag |= CS8;
    150        break;
    151    case 7:
    152        tty.c_cflag |= CS7;
    153        break;
    154    case 6:
    155        tty.c_cflag |= CS6;
    156        break;
    157    case 5:
    158        tty.c_cflag |= CS5;
    159        break;
    160    }
    161    switch (parity) {
    162    default:
    163    case 'N':
    164        break;
    165    case 'E':
    166        tty.c_cflag |= PARENB;
    167        break;
    168    case 'O':
    169        tty.c_cflag |= PARENB | PARODD;
    170        break;
    171    }
    172    if (stop_bits == 2) {
    173        tty.c_cflag |= CSTOPB;
    174    }
    175
    176    tcsetattr(fd, TCSANOW, &tty);
    177}
    178
    179static int tty_serial_ioctl(Chardev *chr, int cmd, void *arg)
    180{
    181    FDChardev *s = FD_CHARDEV(chr);
    182    QIOChannelFile *fioc = QIO_CHANNEL_FILE(s->ioc_in);
    183
    184    switch (cmd) {
    185    case CHR_IOCTL_SERIAL_SET_PARAMS:
    186        {
    187            QEMUSerialSetParams *ssp = arg;
    188            tty_serial_init(fioc->fd,
    189                            ssp->speed, ssp->parity,
    190                            ssp->data_bits, ssp->stop_bits);
    191        }
    192        break;
    193    case CHR_IOCTL_SERIAL_SET_BREAK:
    194        {
    195            int enable = *(int *)arg;
    196            if (enable) {
    197                tcsendbreak(fioc->fd, 1);
    198            }
    199        }
    200        break;
    201    case CHR_IOCTL_SERIAL_GET_TIOCM:
    202        {
    203            int sarg = 0;
    204            int *targ = (int *)arg;
    205            ioctl(fioc->fd, TIOCMGET, &sarg);
    206            *targ = 0;
    207            if (sarg & TIOCM_CTS) {
    208                *targ |= CHR_TIOCM_CTS;
    209            }
    210            if (sarg & TIOCM_CAR) {
    211                *targ |= CHR_TIOCM_CAR;
    212            }
    213            if (sarg & TIOCM_DSR) {
    214                *targ |= CHR_TIOCM_DSR;
    215            }
    216            if (sarg & TIOCM_RI) {
    217                *targ |= CHR_TIOCM_RI;
    218            }
    219            if (sarg & TIOCM_DTR) {
    220                *targ |= CHR_TIOCM_DTR;
    221            }
    222            if (sarg & TIOCM_RTS) {
    223                *targ |= CHR_TIOCM_RTS;
    224            }
    225        }
    226        break;
    227    case CHR_IOCTL_SERIAL_SET_TIOCM:
    228        {
    229            int sarg = *(int *)arg;
    230            int targ = 0;
    231            ioctl(fioc->fd, TIOCMGET, &targ);
    232            targ &= ~(CHR_TIOCM_CTS | CHR_TIOCM_CAR | CHR_TIOCM_DSR
    233                     | CHR_TIOCM_RI | CHR_TIOCM_DTR | CHR_TIOCM_RTS);
    234            if (sarg & CHR_TIOCM_CTS) {
    235                targ |= TIOCM_CTS;
    236            }
    237            if (sarg & CHR_TIOCM_CAR) {
    238                targ |= TIOCM_CAR;
    239            }
    240            if (sarg & CHR_TIOCM_DSR) {
    241                targ |= TIOCM_DSR;
    242            }
    243            if (sarg & CHR_TIOCM_RI) {
    244                targ |= TIOCM_RI;
    245            }
    246            if (sarg & CHR_TIOCM_DTR) {
    247                targ |= TIOCM_DTR;
    248            }
    249            if (sarg & CHR_TIOCM_RTS) {
    250                targ |= TIOCM_RTS;
    251            }
    252            ioctl(fioc->fd, TIOCMSET, &targ);
    253        }
    254        break;
    255    default:
    256        return -ENOTSUP;
    257    }
    258    return 0;
    259}
    260
    261static void qmp_chardev_open_serial(Chardev *chr,
    262                                    ChardevBackend *backend,
    263                                    bool *be_opened,
    264                                    Error **errp)
    265{
    266    ChardevHostdev *serial = backend->u.serial.data;
    267    int fd;
    268
    269    fd = qmp_chardev_open_file_source(serial->device, O_RDWR | O_NONBLOCK,
    270                                      errp);
    271    if (fd < 0) {
    272        return;
    273    }
    274    qemu_set_nonblock(fd);
    275    tty_serial_init(fd, 115200, 'N', 8, 1);
    276
    277    qemu_chr_open_fd(chr, fd, fd);
    278}
    279#endif /* __linux__ || __sun__ */
    280
    281#ifdef HAVE_CHARDEV_SERIAL
    282static void qemu_chr_parse_serial(QemuOpts *opts, ChardevBackend *backend,
    283                                  Error **errp)
    284{
    285    const char *device = qemu_opt_get(opts, "path");
    286    ChardevHostdev *serial;
    287
    288    if (device == NULL) {
    289        error_setg(errp, "chardev: serial/tty: no device path given");
    290        return;
    291    }
    292    backend->type = CHARDEV_BACKEND_KIND_SERIAL;
    293    serial = backend->u.serial.data = g_new0(ChardevHostdev, 1);
    294    qemu_chr_parse_common(opts, qapi_ChardevHostdev_base(serial));
    295    serial->device = g_strdup(device);
    296}
    297
    298static void char_serial_class_init(ObjectClass *oc, void *data)
    299{
    300    ChardevClass *cc = CHARDEV_CLASS(oc);
    301
    302    cc->parse = qemu_chr_parse_serial;
    303    cc->open = qmp_chardev_open_serial;
    304#ifndef _WIN32
    305    cc->chr_ioctl = tty_serial_ioctl;
    306#endif
    307}
    308
    309
    310static const TypeInfo char_serial_type_info = {
    311    .name = TYPE_CHARDEV_SERIAL,
    312#ifdef _WIN32
    313    .parent = TYPE_CHARDEV_WIN,
    314#else
    315    .parent = TYPE_CHARDEV_FD,
    316#endif
    317    .class_init = char_serial_class_init,
    318};
    319
    320static void register_types(void)
    321{
    322    type_register_static(&char_serial_type_info);
    323}
    324
    325type_init(register_types);
    326
    327#endif