Commit 49b6d722 authored by Lei Li's avatar Lei Li Committed by Luiz Capitulino
Browse files

QAPI: Introduce memchar-read QMP command

parent 1f590cf9
Loading
Loading
Loading
Loading
+21 −0
Original line number Diff line number Diff line
@@ -855,6 +855,27 @@ STEXI
Provide writing interface for CirMemCharDriver. Write @var{data}
to char device 'memory'.

ETEXI

    {
        .name       = "memchar_read",
        .args_type  = "device:s,size:i",
        .params     = "device size",
        .help       = "Provide read interface for CirMemCharDriver. Read from"
                      "it and return the data with size.",
        .mhandler.cmd = hmp_memchar_read,
    },

STEXI
@item memchar_read @var{device}
@findex memchar_read
Provide read interface for CirMemCharDriver. Read from char device
'memory' and return the data.

@var{size} is the size of data want to read from. Refer to unencoded
size of the raw data, would adjust to the init size of the memchar
if the requested size is larger than it.

ETEXI

    {
+21 −0
Original line number Diff line number Diff line
@@ -675,6 +675,27 @@ void hmp_memchar_write(Monitor *mon, const QDict *qdict)
    hmp_handle_error(mon, &errp);
}

void hmp_memchar_read(Monitor *mon, const QDict *qdict)
{
    uint32_t size = qdict_get_int(qdict, "size");
    const char *chardev = qdict_get_str(qdict, "device");
    MemCharRead *meminfo;
    Error *errp = NULL;

    meminfo = qmp_memchar_read(chardev, size, false, 0, &errp);
    if (errp) {
        monitor_printf(mon, "%s\n", error_get_pretty(errp));
        error_free(errp);
        return;
    }

    if (meminfo->count > 0) {
        monitor_printf(mon, "%s\n", meminfo->data);
    }

    qapi_free_MemCharRead(meminfo);
}

static void hmp_cont_cb(void *opaque, int err)
{
    if (!err) {
+1 −0
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@ void hmp_cpu(Monitor *mon, const QDict *qdict);
void hmp_memsave(Monitor *mon, const QDict *qdict);
void hmp_pmemsave(Monitor *mon, const QDict *qdict);
void hmp_memchar_write(Monitor *mon, const QDict *qdict);
void hmp_memchar_read(Monitor *mon, const QDict *qdict);
void hmp_cont(Monitor *mon, const QDict *qdict);
void hmp_system_wakeup(Monitor *mon, const QDict *qdict);
void hmp_inject_nmi(Monitor *mon, const QDict *qdict);
+36 −0
Original line number Diff line number Diff line
@@ -362,6 +362,42 @@
  'data': {'device': 'str', 'size': 'int', 'data': 'str',
           '*format': 'DataFormat'} }

##
# @MemCharRead
#
# Result of QMP command memchar-read.
#
# @data: The data read from memchar as string.
#
# @count: The numbers of bytes read from.
#
# Since: 1.4
##
{ 'type': 'MemCharRead',
  'data': { 'data': 'str', 'count': 'int' } }

##
# @memchar-read:
#
# Provide read interface for memchardev. Read from the char
# device 'memory' and return the data.
#
# @device: the name of the memory char device.
#
# @size: the size to read in bytes.
#
# @format: #optional the format of the data want to read from
#          memchardev, by default is 'utf8'.
#
# Returns: @MemCharRead
#          If @device is not a valid memchr device, DeviceNotFound
#
# Since: 1.4
##
{ 'command': 'memchar-read',
  'data': {'device': 'str', 'size': 'int', '*format': 'DataFormat'},
  'returns': 'MemCharRead' }

##
# @CommandInfo:
#
+47 −0
Original line number Diff line number Diff line
@@ -2790,6 +2790,53 @@ void qmp_memchar_write(const char *device, int64_t size,
    }
}

MemCharRead *qmp_memchar_read(const char *device, int64_t size,
                              bool has_format, enum DataFormat format,
                              Error **errp)
{
    CharDriverState *chr;
    guchar *read_data;
    MemCharRead *meminfo;
    size_t count;

    chr = qemu_chr_find(device);
    if (!chr) {
        error_set(errp, QERR_DEVICE_NOT_FOUND, device);
        return NULL;
    }

    if (qemu_is_chr(chr, "memory")) {
        error_setg(errp,"%s is not memory char device", device);
        return NULL;
    }

    if (size <= 0) {
        error_setg(errp, "size must be greater than zero");
        return NULL;
    }

    meminfo = g_malloc0(sizeof(MemCharRead));

    count = qemu_chr_cirmem_count(chr);
    if (count == 0) {
        meminfo->data = g_strdup("");
        return meminfo;
    }

    size = size > count ? count : size;
    read_data = g_malloc0(size + 1);

    meminfo->count = cirmem_chr_read(chr, read_data, size);

    if (has_format && (format == DATA_FORMAT_BASE64)) {
        meminfo->data = g_base64_encode(read_data, (size_t)meminfo->count);
    } else {
        meminfo->data = (char *)read_data;
    }

    return meminfo;
}

QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename)
{
    char host[65], port[33], width[8], height[8];
Loading