From nobody Fri Nov 14 19:40:56 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1761130889; cv=none; d=zohomail.com; s=zohoarc; b=LY2M0rQ+/9p2JFjTPog56qcQGfaCP5hYh2u3LRQX57hn3uHI826qryQ94EUlOIROBqymOrqDpra+n8uvLL0b1lUUlDcnfuv6I6uFLgKjnZX5n0WKTSZTMk6gTyplbWWc4L1P864ixncYpId1XLuK9fUcX2a0lB5bfMEdS8p8RjQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1761130889; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=hl80PiKKKIhAbYMT//gtpWb6aDczjS68wtP0ix3H9v4=; b=GiEMCbYZUg0saB1gnx0YqhC5Ivy0hLcxNH+c+d3Xq8/4hp3eKMTfg7uIBI+rWaTAZS40FnOcgawB2Tr7pAZqDCFI4G90Ug5huGIQMuNFQhYVBIkz6m1JoZBFLjNv5Vn1sCtyyNjF2Hrk8S4AL5QPOVR9RJUgKGj6eTBkh0algGQ= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1761130889787852.0880694151499; Wed, 22 Oct 2025 04:01:29 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vBWaK-0001X7-VL; Wed, 22 Oct 2025 07:00:52 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vBWaI-0001WF-7l for qemu-devel@nongnu.org; Wed, 22 Oct 2025 07:00:50 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vBWa5-0005bw-JW for qemu-devel@nongnu.org; Wed, 22 Oct 2025 07:00:49 -0400 Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-477-PMvssUN6Pm6svyirC36Dlw-1; Wed, 22 Oct 2025 07:00:33 -0400 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 049281956080; Wed, 22 Oct 2025 11:00:32 +0000 (UTC) Received: from sirius.home.kraxel.org (unknown [10.44.32.27]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 5948519560B4; Wed, 22 Oct 2025 11:00:30 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id 14F8918003A0; Wed, 22 Oct 2025 13:00:28 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1761130836; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=hl80PiKKKIhAbYMT//gtpWb6aDczjS68wtP0ix3H9v4=; b=HngG+r/yy9ymDog7PsO7rCZ2DlxVRSmwYcpq9kx8t+YZPGbS6AdPzHgy89RyUXObLsNNz7 uTfB4Eag4VU6PoqudH+S6D8esTlCAu0BeGhamT43NvcDckiEP7chIpmlwfSrn4ZcSpWD0M 6IJvl8IauLICeEckCBs+oYxLRd4HuBI= X-MC-Unique: PMvssUN6Pm6svyirC36Dlw-1 X-Mimecast-MFC-AGG-ID: PMvssUN6Pm6svyirC36Dlw_1761130832 From: Gerd Hoffmann To: qemu-devel@nongnu.org Cc: Paolo Bonzini , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Zhao Liu , Eric Blake , Yanan Wang , Eduardo Habkost , Fabiano Rosas , "Dr. David Alan Gilbert" , Marcel Apfelbaum , Laurent Vivier , Gerd Hoffmann , Markus Armbruster Subject: [PULL 1/3] hw/uefi: add query-firmware-log monitor command Date: Wed, 22 Oct 2025 13:00:25 +0200 Message-ID: <20251022110027.441780-2-kraxel@redhat.com> In-Reply-To: <20251022110027.441780-1-kraxel@redhat.com> References: <20251022110027.441780-1-kraxel@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=kraxel@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1761130897683158500 Content-Type: text/plain; charset="utf-8" Starting with the edk2-stable202508 tag OVMF (and ArmVirt too) have optional support for logging to a memory buffer. There is guest side support -- for example in linux kernels v6.17+ -- to read that buffer. But that might not helpful if your guest stops booting early enough that guest tooling can not be used yet. So host side support to read that log buffer is a useful thing to have. This patch implements the query-firmware-log qmp monitor command to read the firmware log. Reviewed-by: Markus Armbruster Signed-off-by: Gerd Hoffmann Message-ID: <20251017115006.2696991-2-kraxel@redhat.com> --- hw/uefi/ovmf-log.c | 233 +++++++++++++++++++++++++++++++++++++ tests/qtest/qmp-cmd-test.c | 2 + hw/uefi/meson.build | 2 +- qapi/machine.json | 24 ++++ 4 files changed, 260 insertions(+), 1 deletion(-) create mode 100644 hw/uefi/ovmf-log.c diff --git a/hw/uefi/ovmf-log.c b/hw/uefi/ovmf-log.c new file mode 100644 index 000000000000..0d4bd503a06a --- /dev/null +++ b/hw/uefi/ovmf-log.c @@ -0,0 +1,233 @@ +/* + * SPDX-License-Identifier: GPL-2.0-or-later + * + * print ovmf debug log + * + * see OvmfPkg/Library/MemDebugLogLib/ in edk2 + */ + +#include "qemu/osdep.h" +#include "qemu/units.h" +#include "qemu/target-info-qapi.h" +#include "hw/boards.h" +#include "hw/i386/x86.h" +#include "hw/arm/virt.h" +#include "system/dma.h" +#include "monitor/hmp.h" +#include "monitor/monitor.h" +#include "qapi/error.h" +#include "qapi/type-helpers.h" +#include "qapi/qapi-commands-machine.h" + + +/* -----------------------------------------------------------------------= */ +/* copy from edk2 = */ + +#define MEM_DEBUG_LOG_MAGIC1 0x3167646d666d766f /* "ovmfmdg1" */ +#define MEM_DEBUG_LOG_MAGIC2 0x3267646d666d766f /* "ovmfmdg2" */ + +/* + * Mem Debug Log buffer header. + * The Log buffer is circular. Only the most + * recent messages are retained. Older messages + * will be discarded if the buffer overflows. + * The Debug Log starts just after the header. + */ +typedef struct { + /* + * Magic values + * These fields are used by tools to locate the buffer in + * memory. These MUST be the first two fields of the structure. + * Use a 128 bit Magic to vastly reduce the possibility of + * a collision with random data in memory. + */ + uint64_t Magic1; + uint64_t Magic2; + /* + * Header Size + * This MUST be the third field of the structure + */ + uint64_t HeaderSize; + /* + * Debug log size (minus header) + */ + uint64_t DebugLogSize; + /* + * edk2 uses this for locking access. + */ + uint64_t MemDebugLogLock; + /* + * Debug log head offset + */ + uint64_t DebugLogHeadOffset; + /* + * Debug log tail offset + */ + uint64_t DebugLogTailOffset; + /* + * Flag to indicate if the buffer wrapped and was thus truncated. + */ + uint64_t Truncated; + /* + * Firmware Build Version (PcdFirmwareVersionString) + */ + char FirmwareVersion[128]; +} MEM_DEBUG_LOG_HDR; + + +/* -----------------------------------------------------------------------= */ +/* qemu monitor command = */ + +typedef struct { + uint64_t magic1; + uint64_t magic2; +} MemDebugLogMagic; + +/* find log buffer in guest memory by searching for the magic cookie */ +static dma_addr_t find_ovmf_log_range(dma_addr_t start, dma_addr_t end) +{ + static const MemDebugLogMagic magic =3D { + .magic1 =3D MEM_DEBUG_LOG_MAGIC1, + .magic2 =3D MEM_DEBUG_LOG_MAGIC2, + }; + MemDebugLogMagic check; + dma_addr_t step =3D 4 * KiB; + dma_addr_t offset; + + for (offset =3D start; offset < end; offset +=3D step) { + if (dma_memory_read(&address_space_memory, offset, + &check, sizeof(check), + MEMTXATTRS_UNSPECIFIED)) { + /* dma error -> stop searching */ + break; + } + if (memcmp(&magic, &check, sizeof(check)) =3D=3D 0) { + return offset; + } + } + return (dma_addr_t)-1; +} + +static dma_addr_t find_ovmf_log(void) +{ + MachineState *ms =3D MACHINE(qdev_get_machine()); + dma_addr_t start, end, offset; + + if (target_arch() =3D=3D SYS_EMU_TARGET_X86_64 && + object_dynamic_cast(OBJECT(ms), TYPE_X86_MACHINE)) { + X86MachineState *x86ms =3D X86_MACHINE(ms); + + /* early log buffer, static allocation in memfd, sec + early pei */ + offset =3D find_ovmf_log_range(0x800000, 0x900000); + if (offset !=3D -1) { + return offset; + } + + /* + * normal log buffer, dynamically allocated close to end of low me= mory, + * late pei + dxe phase + */ + end =3D x86ms->below_4g_mem_size; + start =3D end - MIN(end, 128 * MiB); + return find_ovmf_log_range(start, end); + } + + if (target_arch() =3D=3D SYS_EMU_TARGET_AARCH64 && + object_dynamic_cast(OBJECT(ms), TYPE_VIRT_MACHINE)) { + VirtMachineState *vms =3D VIRT_MACHINE(ms); + + /* edk2 ArmVirt firmware allocations are in the first 128 MB */ + start =3D vms->memmap[VIRT_MEM].base; + end =3D start + 128 * MiB; + return find_ovmf_log_range(start, end); + } + + return (dma_addr_t)-1; +} + +static void handle_ovmf_log_range(GString *out, + dma_addr_t start, + dma_addr_t end, + Error **errp) +{ + if (start > end) { + return; + } + + size_t len =3D end - start; + g_string_set_size(out, out->len + len); + if (dma_memory_read(&address_space_memory, start, + out->str + (out->len - len), + len, MEMTXATTRS_UNSPECIFIED)) { + error_setg(errp, "can not read firmware log buffer contents"); + return; + } +} + +FirmwareLog *qmp_query_firmware_log(Error **errp) +{ + MEM_DEBUG_LOG_HDR header; + dma_addr_t offset, base; + FirmwareLog *ret; + g_autoptr(GString) log =3D g_string_new(""); + + offset =3D find_ovmf_log(); + if (offset =3D=3D -1) { + error_setg(errp, "firmware log buffer not found"); + return NULL; + } + + if (dma_memory_read(&address_space_memory, offset, + &header, sizeof(header), + MEMTXATTRS_UNSPECIFIED)) { + error_setg(errp, "can not read firmware log buffer header"); + 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; + } + + base =3D offset + header.HeaderSize; + if (header.DebugLogHeadOffset > header.DebugLogTailOffset) { + /* wrap around */ + handle_ovmf_log_range(log, + base + header.DebugLogHeadOffset, + base + header.DebugLogSize, + errp); + if (*errp) { + return NULL; + } + handle_ovmf_log_range(log, + base + 0, + base + header.DebugLogTailOffset, + errp); + if (*errp) { + return NULL; + } + } else { + handle_ovmf_log_range(log, + base + header.DebugLogHeadOffset, + base + header.DebugLogTailOffset, + errp); + if (*errp) { + return NULL; + } + } + + ret =3D g_new0(FirmwareLog, 1); + if (header.FirmwareVersion[0] !=3D '\0') { + ret->version =3D g_strndup(header.FirmwareVersion, + sizeof(header.FirmwareVersion)); + } + ret->log =3D g_base64_encode((const guchar *)log->str, log->len); + return ret; +} diff --git a/tests/qtest/qmp-cmd-test.c b/tests/qtest/qmp-cmd-test.c index cf718761861d..279a8f5614e9 100644 --- a/tests/qtest/qmp-cmd-test.c +++ b/tests/qtest/qmp-cmd-test.c @@ -52,6 +52,8 @@ static int query_error_class(const char *cmd) /* Only valid with accel=3Dtcg */ { "x-query-jit", ERROR_CLASS_GENERIC_ERROR }, { "xen-event-list", ERROR_CLASS_GENERIC_ERROR }, + /* requires firmware with memory buffer logging support */ + { "query-firmware-log", ERROR_CLASS_GENERIC_ERROR }, { NULL, -1 } }; int i; diff --git a/hw/uefi/meson.build b/hw/uefi/meson.build index 91eb95f89e6d..c8f38dfae247 100644 --- a/hw/uefi/meson.build +++ b/hw/uefi/meson.build @@ -1,4 +1,4 @@ -system_ss.add(files('hardware-info.c')) +system_ss.add(files('hardware-info.c', 'ovmf-log.c')) =20 uefi_vars_ss =3D ss.source_set() if (config_all_devices.has_key('CONFIG_UEFI_VARS')) diff --git a/qapi/machine.json b/qapi/machine.json index 038eab281c78..96133e5c71cf 100644 --- a/qapi/machine.json +++ b/qapi/machine.json @@ -1839,6 +1839,30 @@ 'returns': 'HumanReadableText', 'features': [ 'unstable' ]} =20 +## +# @FirmwareLog: +# +# @version: Firmware version. +# +# @log: Firmware debug log, in base64 encoding. First and last log +# line might be incomplete. +# +# Since: 10.2 +## +{ 'struct': 'FirmwareLog', + 'data': { '*version': 'str', + 'log': 'str' } } + +## +# @query-firmware-log: +# +# Find firmware memory log buffer in guest memory, return content. +# +# Since: 10.2 +## +{ 'command': 'query-firmware-log', + 'returns': 'FirmwareLog' } + ## # @dump-skeys: # --=20 2.51.0 From nobody Fri Nov 14 19:40:56 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1761130966; cv=none; d=zohomail.com; s=zohoarc; b=Ie6P/zQeBG1A+XtqXSYoc/QTkd+xlYF3EFUn9akZ3xYasm6bDja+X3VIPFtfJ5z5B3VimcDqyeCkcLwAnMDrUvvaPoCEa0E0iZhbtKBXCNcggPpm7d23GXmdUnGNfCOeh5y1O7qUrgQUpg65YZflY0eNfKsOkqYsUPSdS6N+AT4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1761130966; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=/bvTOU0HYOLSAJaQ2Au/rTDDGroYRoRbK9NjFAix4UU=; b=YLcUJBpqAe/HwtXx52G0KyCWC28YiaYwdmuGl8VhqPahDZqZfJd0G8XtXmM5fvf6Uqs6lT1ONNPO89DVD7q8GJmmAa/v+8/qK5i/fyRhINOsyWXUGCw0sgsq/rTTJ8s7XVOerM4JGFtbX/r9Pw3I5HU4iWGyZ3tn5Hrf1/xeYzM= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1761130966923647.9516341669648; Wed, 22 Oct 2025 04:02:46 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vBWaM-0001Y3-II; Wed, 22 Oct 2025 07:00:54 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vBWaI-0001WO-8f for qemu-devel@nongnu.org; Wed, 22 Oct 2025 07:00:50 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vBWaA-0005d2-Cv for qemu-devel@nongnu.org; Wed, 22 Oct 2025 07:00:49 -0400 Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-112-YhbvZUUOOl6vF_HyeKMIfw-1; Wed, 22 Oct 2025 07:00:37 -0400 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 5275F19560B4; Wed, 22 Oct 2025 11:00:35 +0000 (UTC) Received: from sirius.home.kraxel.org (unknown [10.44.32.27]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 27601180057E; Wed, 22 Oct 2025 11:00:34 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id 2A30018003AA; Wed, 22 Oct 2025 13:00:28 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1761130840; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=/bvTOU0HYOLSAJaQ2Au/rTDDGroYRoRbK9NjFAix4UU=; b=IpIO48n4XZuHizGcuDTdIRy0U2FJvykvvYYMZqq8e0b29H7cmAI2VVheYygtkQCPwws8nA dvyefwU3daEzU2q+lxqeK8rDXrWTBrCZ4AKZzQ7YFKczDBehBOKXtyo4x+XLvve/5ch41d Q6xLmcXKhVLJN2B6X6993AAqv6eGUDM= X-MC-Unique: YhbvZUUOOl6vF_HyeKMIfw-1 X-Mimecast-MFC-AGG-ID: YhbvZUUOOl6vF_HyeKMIfw_1761130835 From: Gerd Hoffmann To: qemu-devel@nongnu.org Cc: Paolo Bonzini , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Zhao Liu , Eric Blake , Yanan Wang , Eduardo Habkost , Fabiano Rosas , "Dr. David Alan Gilbert" , Marcel Apfelbaum , Laurent Vivier , Gerd Hoffmann , Markus Armbruster Subject: [PULL 2/3] hw/uefi: add 'info firmware-log' hmp monitor command. Date: Wed, 22 Oct 2025 13:00:26 +0200 Message-ID: <20251022110027.441780-3-kraxel@redhat.com> In-Reply-To: <20251022110027.441780-1-kraxel@redhat.com> References: <20251022110027.441780-1-kraxel@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=kraxel@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1761130970123154100 Content-Type: text/plain; charset="utf-8" This adds the hmp variant of the query-firmware-log qmp command. Reviewed-by: Markus Armbruster Signed-off-by: Gerd Hoffmann Message-ID: <20251017115006.2696991-3-kraxel@redhat.com> --- include/monitor/hmp.h | 1 + hw/uefi/ovmf-log.c | 27 +++++++++++++++++++++++++++ hmp-commands-info.hx | 13 +++++++++++++ 3 files changed, 41 insertions(+) diff --git a/include/monitor/hmp.h b/include/monitor/hmp.h index 897dfaa2b6d9..83721b5ffc6d 100644 --- a/include/monitor/hmp.h +++ b/include/monitor/hmp.h @@ -179,5 +179,6 @@ void hmp_boot_set(Monitor *mon, const QDict *qdict); void hmp_info_mtree(Monitor *mon, const QDict *qdict); void hmp_info_cryptodev(Monitor *mon, const QDict *qdict); void hmp_dumpdtb(Monitor *mon, const QDict *qdict); +void hmp_info_firmware_log(Monitor *mon, const QDict *qdict); =20 #endif diff --git a/hw/uefi/ovmf-log.c b/hw/uefi/ovmf-log.c index 0d4bd503a06a..fe8acbd19236 100644 --- a/hw/uefi/ovmf-log.c +++ b/hw/uefi/ovmf-log.c @@ -231,3 +231,30 @@ FirmwareLog *qmp_query_firmware_log(Error **errp) ret->log =3D g_base64_encode((const guchar *)log->str, log->len); return ret; } + +void hmp_info_firmware_log(Monitor *mon, const QDict *qdict) +{ + g_autofree gchar *log_esc =3D NULL; + g_autofree guchar *log_out =3D NULL; + Error *err =3D NULL; + FirmwareLog *log; + gsize log_len; + + log =3D qmp_query_firmware_log(&err); + if (err) { + hmp_handle_error(mon, err); + return; + } + + g_assert(log !=3D NULL); + g_assert(log->log !=3D NULL); + + if (log->version) { + g_autofree gchar *esc =3D g_strescape(log->version, NULL); + monitor_printf(mon, "[ firmware version: %s ]\n", esc); + } + + log_out =3D g_base64_decode(log->log, &log_len); + log_esc =3D g_strescape((gchar *)log_out, "\r\n"); + monitor_printf(mon, "%s\n", log_esc); +} diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx index 25b4aed51f56..33cf740bbc1b 100644 --- a/hmp-commands-info.hx +++ b/hmp-commands-info.hx @@ -995,3 +995,16 @@ SRST ``info cryptodev`` Show the crypto devices. ERST + + { + .name =3D "firmware-log", + .args_type =3D "", + .params =3D "", + .help =3D "show the firmware (ovmf) debug log", + .cmd =3D hmp_info_firmware_log, + }, + +SRST + ``info firmware-log`` + Show the firmware (ovmf) debug log. +ERST --=20 2.51.0 From nobody Fri Nov 14 19:40:56 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1761130882; cv=none; d=zohomail.com; s=zohoarc; b=ivZJPADQJA7HOCCjjhgw3rbUI0yYoRC8/wp8/yMx8v7iKGKK4aESNNfJYIEjz2GHxRP1dJMFYvBN1P9BtgNGJfTiH2HyuUryyzSokm8sI9BbHY01KiuBI7Mo2yUYuySZ3hE0l1Ik9zzCHCPgiGVebNGES1fbQ9n3w8eRVkNslqM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1761130882; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=cWO+HWjLIQTLIzxJ/Yn1KzFJP9Nkv8LoxMvKWhvh7Bk=; b=QjxWnf7SP78cROTT+x5wJ0c20AN+OyT9JkWmMuFYoMCwZ+ZCiGvnEEI6vAlbKZJxk0xyZQFFBI6W5BW/dFRWMnfYuUFwUcE5W2ewYLA+V2S2hAq/Sp8KCuGjtHpxWMpjWpvhnXMh5h8j1ovxfhPXMbBqHi9BNaVywAAg+xLoxxo= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1761130882828989.917036173531; Wed, 22 Oct 2025 04:01:22 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vBWaN-0001Y6-3X; Wed, 22 Oct 2025 07:00:55 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vBWaI-0001WV-DL for qemu-devel@nongnu.org; Wed, 22 Oct 2025 07:00:50 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vBWaA-0005dM-OH for qemu-devel@nongnu.org; Wed, 22 Oct 2025 07:00:50 -0400 Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-278-1wJRCyd_M0KXLEGyh8_bpQ-1; Wed, 22 Oct 2025 07:00:37 -0400 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id BBD741801359; Wed, 22 Oct 2025 11:00:35 +0000 (UTC) Received: from sirius.home.kraxel.org (unknown [10.44.32.27]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 65FF11955F22; Wed, 22 Oct 2025 11:00:34 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id 3FECC1800784; Wed, 22 Oct 2025 13:00:28 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1761130841; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=cWO+HWjLIQTLIzxJ/Yn1KzFJP9Nkv8LoxMvKWhvh7Bk=; b=Dv+FWpi0oW6cy/eF8GD+VXQqDBJ23Q8/vyfvT8Qnfja0yUXVNcNlIiY4QhnlaSIb+4XA2D jCR9wC1ne4BPW0g5NklC/Z7Bq6haOpJwcTd3dIwte//xlPsk7/mSTKZRxULmMn8Fs9GaIJ +aEf0TpEauk4zJas8MCsmhvZfLTZiGE= X-MC-Unique: 1wJRCyd_M0KXLEGyh8_bpQ-1 X-Mimecast-MFC-AGG-ID: 1wJRCyd_M0KXLEGyh8_bpQ_1761130836 From: Gerd Hoffmann To: qemu-devel@nongnu.org Cc: Paolo Bonzini , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Zhao Liu , Eric Blake , Yanan Wang , Eduardo Habkost , Fabiano Rosas , "Dr. David Alan Gilbert" , Marcel Apfelbaum , Laurent Vivier , Gerd Hoffmann , Markus Armbruster Subject: [PULL 3/3] hw/uefi/ovmf-log: add maxsize parameter Date: Wed, 22 Oct 2025 13:00:27 +0200 Message-ID: <20251022110027.441780-4-kraxel@redhat.com> In-Reply-To: <20251022110027.441780-1-kraxel@redhat.com> References: <20251022110027.441780-1-kraxel@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=kraxel@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1761130893663158500 Content-Type: text/plain; charset="utf-8" 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. Acked-by: Markus Armbruster Signed-off-by: Gerd Hoffmann Message-ID: <20251017115006.2696991-4-kraxel@redhat.com> --- 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" =20 =20 /* -----------------------------------------------------------------------= */ @@ -164,7 +165,8 @@ static void handle_ovmf_log_range(GString *out, } } =20 -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; } =20 - 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; } =20 + if (have_max_size) { + if (max_size > MiB) { + error_setg(errp, "parameter 'max-size' exceeds 1MiB"); + return NULL; + } + } else { + max_size =3D 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 =3D header.DebugLogTailOffset - max_= size; + } else { + uint64_t max_chunk =3D max_size - header.DebugLogTailOffset; + if (header.DebugLogSize > max_chunk && + header.DebugLogHeadOffset < header.DebugLogSize - max_chun= k) { + header.DebugLogHeadOffset =3D header.DebugLogSize - max_ch= unk; + } + } + } else { + if (header.DebugLogTailOffset > max_size && + header.DebugLogHeadOffset < header.DebugLogTailOffset - max_si= ze) { + header.DebugLogHeadOffset =3D header.DebugLogTailOffset - max_= size; + } + } + base =3D 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 =3D NULL; FirmwareLog *log; gsize log_len; + int64_t maxsize; =20 - log =3D qmp_query_firmware_log(&err); + maxsize =3D qdict_get_try_int(qdict, "max-size", -1); + log =3D qmp_query_firmware_log(maxsize !=3D -1, (uint64_t)maxsize, &er= r); 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 =20 { .name =3D "firmware-log", - .args_type =3D "", - .params =3D "", + .args_type =3D "max-size:o?", + .params =3D "[max-size]", .help =3D "show the firmware (ovmf) debug log", .cmd =3D 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' } =20 ## --=20 2.51.0