Allow limiting the amount of log output sent. Allow up to 1 MiB. In case the guest log buffer is larger than 1 MiB limit the output instead of throwing an error.
Signed-off-by: Gerd Hoffmann <[email protected]> --- hw/uefi/ovmf-log.c | 42 ++++++++++++++++++++++++++++++++++-------- hmp-commands-info.hx | 4 ++-- qapi/machine.json | 5 +++++ 3 files changed, 41 insertions(+), 10 deletions(-) diff --git a/hw/uefi/ovmf-log.c b/hw/uefi/ovmf-log.c index fe8acbd19236..98ebb0209491 100644 --- a/hw/uefi/ovmf-log.c +++ b/hw/uefi/ovmf-log.c @@ -18,6 +18,7 @@ #include "qapi/error.h" #include "qapi/type-helpers.h" #include "qapi/qapi-commands-machine.h" +#include "qobject/qdict.h" /* ----------------------------------------------------------------------- */ @@ -164,7 +165,8 @@ static void handle_ovmf_log_range(GString *out, } } -FirmwareLog *qmp_query_firmware_log(Error **errp) +FirmwareLog *qmp_query_firmware_log(bool have_max_size, uint64_t max_size, + Error **errp) { MEM_DEBUG_LOG_HDR header; dma_addr_t offset, base; @@ -184,18 +186,40 @@ FirmwareLog *qmp_query_firmware_log(Error **errp) return NULL; } - if (header.DebugLogSize > MiB) { - /* default size is 128k (32 pages), allow up to 1M */ - error_setg(errp, "firmware log: log buffer is too big"); - return NULL; - } - if (header.DebugLogHeadOffset > header.DebugLogSize || header.DebugLogTailOffset > header.DebugLogSize) { error_setg(errp, "firmware log buffer header is invalid"); return NULL; } + if (have_max_size) { + if (max_size > MiB) { + error_setg(errp, "parameter 'max-size' exceeds 1MiB"); + return NULL; + } + } else { + max_size = MiB; + } + + /* adjust header.DebugLogHeadOffset so we return at most maxsize bytes */ + if (header.DebugLogHeadOffset > header.DebugLogTailOffset) { + /* wrap around */ + if (header.DebugLogTailOffset > max_size) { + header.DebugLogHeadOffset = header.DebugLogTailOffset - max_size; + } else { + uint64_t max_chunk = max_size - header.DebugLogTailOffset; + if (header.DebugLogSize > max_chunk && + header.DebugLogHeadOffset < header.DebugLogSize - max_chunk) { + header.DebugLogHeadOffset = header.DebugLogSize - max_chunk; + } + } + } else { + if (header.DebugLogTailOffset > max_size && + header.DebugLogHeadOffset < header.DebugLogTailOffset - max_size) { + header.DebugLogHeadOffset = header.DebugLogTailOffset - max_size; + } + } + base = offset + header.HeaderSize; if (header.DebugLogHeadOffset > header.DebugLogTailOffset) { /* wrap around */ @@ -239,8 +263,10 @@ void hmp_info_firmware_log(Monitor *mon, const QDict *qdict) Error *err = NULL; FirmwareLog *log; gsize log_len; + int64_t maxsize; - log = qmp_query_firmware_log(&err); + maxsize = qdict_get_try_int(qdict, "max-size", -1); + log = qmp_query_firmware_log(maxsize != -1, (uint64_t)maxsize, &err); if (err) { hmp_handle_error(mon, err); return; diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx index 33cf740bbc1b..2a7f5810d706 100644 --- a/hmp-commands-info.hx +++ b/hmp-commands-info.hx @@ -998,8 +998,8 @@ ERST { .name = "firmware-log", - .args_type = "", - .params = "", + .args_type = "max-size:o?", + .params = "[max-size]", .help = "show the firmware (ovmf) debug log", .cmd = hmp_info_firmware_log, }, diff --git a/qapi/machine.json b/qapi/machine.json index 96133e5c71cf..c6dc6fe69b5c 100644 --- a/qapi/machine.json +++ b/qapi/machine.json @@ -1858,9 +1858,14 @@ # # Find firmware memory log buffer in guest memory, return content. # +# @max-size: limit the amount of log data returned. Up to 1 MiB of +# log data is allowed. In case the amount of log data is +# larger than @max-size the tail of the log is returned. +# # Since: 10.2 ## { 'command': 'query-firmware-log', + 'data': { '*max-size': 'size' }, 'returns': 'FirmwareLog' } ## -- 2.51.0
