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-win.c (6503B)


      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/main-loop.h"
     27#include "qemu/module.h"
     28#include "qapi/error.h"
     29#include "chardev/char-win.h"
     30
     31static void win_chr_read(Chardev *chr, DWORD len)
     32{
     33    WinChardev *s = WIN_CHARDEV(chr);
     34    int max_size = qemu_chr_be_can_write(chr);
     35    int ret, err;
     36    uint8_t buf[CHR_READ_BUF_LEN];
     37    DWORD size;
     38
     39    if (len > max_size) {
     40        len = max_size;
     41    }
     42    if (len == 0) {
     43        return;
     44    }
     45
     46    ZeroMemory(&s->orecv, sizeof(s->orecv));
     47    s->orecv.hEvent = s->hrecv;
     48    ret = ReadFile(s->file, buf, len, &size, &s->orecv);
     49    if (!ret) {
     50        err = GetLastError();
     51        if (err == ERROR_IO_PENDING) {
     52            ret = GetOverlappedResult(s->file, &s->orecv, &size, TRUE);
     53        }
     54    }
     55
     56    if (size > 0) {
     57        qemu_chr_be_write(chr, buf, size);
     58    }
     59}
     60
     61static int win_chr_serial_poll(void *opaque)
     62{
     63    Chardev *chr = CHARDEV(opaque);
     64    WinChardev *s = WIN_CHARDEV(opaque);
     65    COMSTAT status;
     66    DWORD comerr;
     67
     68    ClearCommError(s->file, &comerr, &status);
     69    if (status.cbInQue > 0) {
     70        win_chr_read(chr, status.cbInQue);
     71        return 1;
     72    }
     73    return 0;
     74}
     75
     76int win_chr_serial_init(Chardev *chr, const char *filename, Error **errp)
     77{
     78    WinChardev *s = WIN_CHARDEV(chr);
     79    COMMCONFIG comcfg;
     80    COMMTIMEOUTS cto = { 0, 0, 0, 0, 0};
     81    COMSTAT comstat;
     82    DWORD size;
     83    DWORD err;
     84
     85    s->hsend = CreateEvent(NULL, TRUE, FALSE, NULL);
     86    if (!s->hsend) {
     87        error_setg(errp, "Failed CreateEvent");
     88        goto fail;
     89    }
     90    s->hrecv = CreateEvent(NULL, TRUE, FALSE, NULL);
     91    if (!s->hrecv) {
     92        error_setg(errp, "Failed CreateEvent");
     93        goto fail;
     94    }
     95
     96    s->file = CreateFile(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
     97                      OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
     98    if (s->file == INVALID_HANDLE_VALUE) {
     99        error_setg_win32(errp, GetLastError(), "Failed CreateFile");
    100        s->file = NULL;
    101        goto fail;
    102    }
    103
    104    if (!SetupComm(s->file, NRECVBUF, NSENDBUF)) {
    105        error_setg(errp, "Failed SetupComm");
    106        goto fail;
    107    }
    108
    109    ZeroMemory(&comcfg, sizeof(COMMCONFIG));
    110    size = sizeof(COMMCONFIG);
    111    GetDefaultCommConfig(filename, &comcfg, &size);
    112    comcfg.dcb.DCBlength = sizeof(DCB);
    113    CommConfigDialog(filename, NULL, &comcfg);
    114
    115    if (!SetCommState(s->file, &comcfg.dcb)) {
    116        error_setg(errp, "Failed SetCommState");
    117        goto fail;
    118    }
    119
    120    if (!SetCommMask(s->file, EV_ERR)) {
    121        error_setg(errp, "Failed SetCommMask");
    122        goto fail;
    123    }
    124
    125    cto.ReadIntervalTimeout = MAXDWORD;
    126    if (!SetCommTimeouts(s->file, &cto)) {
    127        error_setg(errp, "Failed SetCommTimeouts");
    128        goto fail;
    129    }
    130
    131    if (!ClearCommError(s->file, &err, &comstat)) {
    132        error_setg(errp, "Failed ClearCommError");
    133        goto fail;
    134    }
    135    qemu_add_polling_cb(win_chr_serial_poll, chr);
    136    return 0;
    137
    138 fail:
    139    return -1;
    140}
    141
    142int win_chr_pipe_poll(void *opaque)
    143{
    144    Chardev *chr = CHARDEV(opaque);
    145    WinChardev *s = WIN_CHARDEV(opaque);
    146    DWORD size;
    147
    148    PeekNamedPipe(s->file, NULL, 0, NULL, &size, NULL);
    149    if (size > 0) {
    150        win_chr_read(chr, size);
    151        return 1;
    152    }
    153    return 0;
    154}
    155
    156/* Called with chr_write_lock held.  */
    157static int win_chr_write(Chardev *chr, const uint8_t *buf, int len1)
    158{
    159    WinChardev *s = WIN_CHARDEV(chr);
    160    DWORD len, ret, size, err;
    161
    162    len = len1;
    163    ZeroMemory(&s->osend, sizeof(s->osend));
    164    s->osend.hEvent = s->hsend;
    165    while (len > 0) {
    166        if (s->hsend) {
    167            ret = WriteFile(s->file, buf, len, &size, &s->osend);
    168        } else {
    169            ret = WriteFile(s->file, buf, len, &size, NULL);
    170        }
    171        if (!ret) {
    172            err = GetLastError();
    173            if (err == ERROR_IO_PENDING) {
    174                ret = GetOverlappedResult(s->file, &s->osend, &size, TRUE);
    175                if (ret) {
    176                    buf += size;
    177                    len -= size;
    178                } else {
    179                    break;
    180                }
    181            } else {
    182                break;
    183            }
    184        } else {
    185            buf += size;
    186            len -= size;
    187        }
    188    }
    189    return len1 - len;
    190}
    191
    192static void char_win_finalize(Object *obj)
    193{
    194    Chardev *chr = CHARDEV(obj);
    195    WinChardev *s = WIN_CHARDEV(chr);
    196
    197    if (s->hsend) {
    198        CloseHandle(s->hsend);
    199    }
    200    if (s->hrecv) {
    201        CloseHandle(s->hrecv);
    202    }
    203    if (!s->keep_open && s->file) {
    204        CloseHandle(s->file);
    205    }
    206    if (s->fpipe) {
    207        qemu_del_polling_cb(win_chr_pipe_poll, chr);
    208    } else {
    209        qemu_del_polling_cb(win_chr_serial_poll, chr);
    210    }
    211
    212    qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
    213}
    214
    215void win_chr_set_file(Chardev *chr, HANDLE file, bool keep_open)
    216{
    217    WinChardev *s = WIN_CHARDEV(chr);
    218
    219    s->keep_open = keep_open;
    220    s->file = file;
    221}
    222
    223static void char_win_class_init(ObjectClass *oc, void *data)
    224{
    225    ChardevClass *cc = CHARDEV_CLASS(oc);
    226
    227    cc->chr_write = win_chr_write;
    228}
    229
    230static const TypeInfo char_win_type_info = {
    231    .name = TYPE_CHARDEV_WIN,
    232    .parent = TYPE_CHARDEV,
    233    .instance_size = sizeof(WinChardev),
    234    .instance_finalize = char_win_finalize,
    235    .class_init = char_win_class_init,
    236    .abstract = true,
    237};
    238
    239static void register_types(void)
    240{
    241    type_register_static(&char_win_type_info);
    242}
    243
    244type_init(register_types);