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

wavcapture.c (4901B)


      1#include "qemu/osdep.h"
      2#include "qemu/qemu-print.h"
      3#include "qapi/error.h"
      4#include "qemu/error-report.h"
      5#include "audio.h"
      6
      7typedef struct {
      8    FILE *f;
      9    int bytes;
     10    char *path;
     11    int freq;
     12    int bits;
     13    int nchannels;
     14    CaptureVoiceOut *cap;
     15} WAVState;
     16
     17/* VICE code: Store number as little endian. */
     18static void le_store (uint8_t *buf, uint32_t val, int len)
     19{
     20    int i;
     21    for (i = 0; i < len; i++) {
     22        buf[i] = (uint8_t) (val & 0xff);
     23        val >>= 8;
     24    }
     25}
     26
     27static void wav_notify (void *opaque, audcnotification_e cmd)
     28{
     29    (void) opaque;
     30    (void) cmd;
     31}
     32
     33static void wav_destroy (void *opaque)
     34{
     35    WAVState *wav = opaque;
     36    uint8_t rlen[4];
     37    uint8_t dlen[4];
     38    uint32_t datalen = wav->bytes;
     39    uint32_t rifflen = datalen + 36;
     40
     41    if (wav->f) {
     42        le_store (rlen, rifflen, 4);
     43        le_store (dlen, datalen, 4);
     44
     45        if (fseek (wav->f, 4, SEEK_SET)) {
     46            error_report("wav_destroy: rlen fseek failed: %s",
     47                         strerror(errno));
     48            goto doclose;
     49        }
     50        if (fwrite (rlen, 4, 1, wav->f) != 1) {
     51            error_report("wav_destroy: rlen fwrite failed: %s",
     52                         strerror(errno));
     53            goto doclose;
     54        }
     55        if (fseek (wav->f, 32, SEEK_CUR)) {
     56            error_report("wav_destroy: dlen fseek failed: %s",
     57                         strerror(errno));
     58            goto doclose;
     59        }
     60        if (fwrite (dlen, 1, 4, wav->f) != 4) {
     61            error_report("wav_destroy: dlen fwrite failed: %s",
     62                         strerror(errno));
     63            goto doclose;
     64        }
     65    doclose:
     66        if (fclose (wav->f)) {
     67            error_report("wav_destroy: fclose failed: %s", strerror(errno));
     68        }
     69    }
     70
     71    g_free (wav->path);
     72}
     73
     74static void wav_capture(void *opaque, const void *buf, int size)
     75{
     76    WAVState *wav = opaque;
     77
     78    if (fwrite (buf, size, 1, wav->f) != 1) {
     79        error_report("wav_capture: fwrite error: %s", strerror(errno));
     80    }
     81    wav->bytes += size;
     82}
     83
     84static void wav_capture_destroy (void *opaque)
     85{
     86    WAVState *wav = opaque;
     87
     88    AUD_del_capture (wav->cap, wav);
     89    g_free (wav);
     90}
     91
     92static void wav_capture_info (void *opaque)
     93{
     94    WAVState *wav = opaque;
     95    char *path = wav->path;
     96
     97    qemu_printf("Capturing audio(%d,%d,%d) to %s: %d bytes\n",
     98                wav->freq, wav->bits, wav->nchannels,
     99                path ? path : "<not available>", wav->bytes);
    100}
    101
    102static struct capture_ops wav_capture_ops = {
    103    .destroy = wav_capture_destroy,
    104    .info = wav_capture_info
    105};
    106
    107int wav_start_capture(AudioState *state, CaptureState *s, const char *path,
    108                      int freq, int bits, int nchannels)
    109{
    110    WAVState *wav;
    111    uint8_t hdr[] = {
    112        0x52, 0x49, 0x46, 0x46, 0x00, 0x00, 0x00, 0x00, 0x57, 0x41, 0x56,
    113        0x45, 0x66, 0x6d, 0x74, 0x20, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00,
    114        0x02, 0x00, 0x44, 0xac, 0x00, 0x00, 0x10, 0xb1, 0x02, 0x00, 0x04,
    115        0x00, 0x10, 0x00, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, 0x00
    116    };
    117    struct audsettings as;
    118    struct audio_capture_ops ops;
    119    int stereo, bits16, shift;
    120    CaptureVoiceOut *cap;
    121
    122    if (bits != 8 && bits != 16) {
    123        error_report("incorrect bit count %d, must be 8 or 16", bits);
    124        return -1;
    125    }
    126
    127    if (nchannels != 1 && nchannels != 2) {
    128        error_report("incorrect channel count %d, must be 1 or 2",
    129                     nchannels);
    130        return -1;
    131    }
    132
    133    stereo = nchannels == 2;
    134    bits16 = bits == 16;
    135
    136    as.freq = freq;
    137    as.nchannels = 1 << stereo;
    138    as.fmt = bits16 ? AUDIO_FORMAT_S16 : AUDIO_FORMAT_U8;
    139    as.endianness = 0;
    140
    141    ops.notify = wav_notify;
    142    ops.capture = wav_capture;
    143    ops.destroy = wav_destroy;
    144
    145    wav = g_malloc0 (sizeof (*wav));
    146
    147    shift = bits16 + stereo;
    148    hdr[34] = bits16 ? 0x10 : 0x08;
    149
    150    le_store (hdr + 22, as.nchannels, 2);
    151    le_store (hdr + 24, freq, 4);
    152    le_store (hdr + 28, freq << shift, 4);
    153    le_store (hdr + 32, 1 << shift, 2);
    154
    155    wav->f = fopen (path, "wb");
    156    if (!wav->f) {
    157        error_report("Failed to open wave file `%s': %s",
    158                     path, strerror(errno));
    159        g_free (wav);
    160        return -1;
    161    }
    162
    163    wav->path = g_strdup (path);
    164    wav->bits = bits;
    165    wav->nchannels = nchannels;
    166    wav->freq = freq;
    167
    168    if (fwrite (hdr, sizeof (hdr), 1, wav->f) != 1) {
    169        error_report("Failed to write header: %s", strerror(errno));
    170        goto error_free;
    171    }
    172
    173    cap = AUD_add_capture(state, &as, &ops, wav);
    174    if (!cap) {
    175        error_report("Failed to add audio capture");
    176        goto error_free;
    177    }
    178
    179    wav->cap = cap;
    180    s->opaque = wav;
    181    s->ops = wav_capture_ops;
    182    return 0;
    183
    184error_free:
    185    g_free (wav->path);
    186    if (fclose (wav->f)) {
    187        error_report("Failed to close wave file: %s", strerror(errno));
    188    }
    189    g_free (wav);
    190    return -1;
    191}