mirror of
https://github.com/qemu/qemu.git
synced 2026-02-04 02:24:51 +00:00
hw/uefi: add pcap support
Add pcapfile property to uevi-vars-* devices, allowing to write out a capture of the communication traffic between uefi firmware and qemu. Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Message-ID: <20260114110406.3500357-3-kraxel@redhat.com> [PMD: Wrap long line to avoid checkpatch.pl warning] Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
This commit is contained in:
committed by
Philippe Mathieu-Daudé
parent
9aac42720c
commit
41e047ad66
@@ -3,6 +3,7 @@ system_ss.add(files('hardware-info.c', 'ovmf-log.c'))
|
||||
uefi_vars_ss = ss.source_set()
|
||||
if (config_all_devices.has_key('CONFIG_UEFI_VARS'))
|
||||
uefi_vars_ss.add(files('var-service-core.c',
|
||||
'var-service-pcap.c',
|
||||
'var-service-json.c',
|
||||
'var-service-vars.c',
|
||||
'var-service-auth.c',
|
||||
|
||||
@@ -101,6 +101,8 @@ static uint32_t uefi_vars_cmd_mm(uefi_vars_state *uv, bool dma_mode)
|
||||
}
|
||||
memset(uv->buffer + size, 0, uv->buf_size - size);
|
||||
|
||||
uefi_vars_pcap_request(uv, uv->buffer, size);
|
||||
|
||||
/* dispatch */
|
||||
if (qemu_uuid_is_equal(&mhdr->guid, &EfiSmmVariableProtocolGuid)) {
|
||||
retval = uefi_vars_mm_vars_proto(uv);
|
||||
@@ -127,6 +129,8 @@ static uint32_t uefi_vars_cmd_mm(uefi_vars_state *uv, bool dma_mode)
|
||||
retval = UEFI_VARS_STS_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
uefi_vars_pcap_reply(uv, uv->buffer, sizeof(*mhdr) + mhdr->length);
|
||||
|
||||
/* write buffer */
|
||||
if (dma_mode) {
|
||||
dma_memory_write(&address_space_memory, dma,
|
||||
@@ -163,6 +167,8 @@ void uefi_vars_hard_reset(uefi_vars_state *uv)
|
||||
uefi_vars_clear_volatile(uv);
|
||||
uefi_vars_policies_clear(uv);
|
||||
uefi_vars_auth_init(uv);
|
||||
|
||||
uefi_vars_pcap_reset(uv);
|
||||
}
|
||||
|
||||
static uint32_t uefi_vars_cmd(uefi_vars_state *uv, uint32_t cmd)
|
||||
@@ -319,4 +325,5 @@ void uefi_vars_realize(uefi_vars_state *uv, Error **errp)
|
||||
{
|
||||
uefi_vars_json_init(uv, errp);
|
||||
uefi_vars_json_load(uv, errp);
|
||||
uefi_vars_pcap_init(uv, errp);
|
||||
}
|
||||
|
||||
95
hw/uefi/var-service-pcap.c
Normal file
95
hw/uefi/var-service-pcap.c
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qemu/pcap.h"
|
||||
#include "system/dma.h"
|
||||
|
||||
#include "hw/uefi/var-service.h"
|
||||
|
||||
#define LINKTYPE_EDK2_MM 302
|
||||
|
||||
#define SNAPLEN (64 * 1024)
|
||||
#define TYPE_RESET 0x01
|
||||
#define TYPE_REQUEST 0x02
|
||||
#define TYPE_REPLY 0x03
|
||||
|
||||
static void uefi_vars_pcap_header(FILE *fp)
|
||||
{
|
||||
static const struct pcap_hdr header = {
|
||||
.magic_number = PCAP_MAGIC,
|
||||
.version_major = PCAP_MAJOR,
|
||||
.version_minor = PCAP_MINOR,
|
||||
.snaplen = SNAPLEN,
|
||||
.network = LINKTYPE_EDK2_MM,
|
||||
};
|
||||
|
||||
fwrite(&header, sizeof(header), 1, fp);
|
||||
fflush(fp);
|
||||
}
|
||||
|
||||
static void uefi_vars_pcap_packet(FILE *fp, uint32_t type,
|
||||
void *buffer, size_t size)
|
||||
{
|
||||
struct pcaprec_hdr header;
|
||||
struct timeval tv;
|
||||
uint32_t orig_len = size + sizeof(type);
|
||||
uint32_t incl_len = MIN(orig_len, SNAPLEN);
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
header.ts_sec = tv.tv_sec;
|
||||
header.ts_usec = tv.tv_usec;
|
||||
header.incl_len = incl_len;
|
||||
header.orig_len = orig_len;
|
||||
|
||||
fwrite(&header, sizeof(header), 1, fp);
|
||||
fwrite(&type, sizeof(type), 1, fp);
|
||||
if (buffer) {
|
||||
fwrite(buffer, incl_len - sizeof(type), 1, fp);
|
||||
}
|
||||
fflush(fp);
|
||||
}
|
||||
|
||||
void uefi_vars_pcap_init(uefi_vars_state *uv, Error **errp)
|
||||
{
|
||||
int fd;
|
||||
|
||||
if (!uv->pcapfile) {
|
||||
return;
|
||||
}
|
||||
|
||||
fd = qemu_create(uv->pcapfile,
|
||||
O_WRONLY | O_TRUNC | O_BINARY,
|
||||
0666, errp);
|
||||
if (fd < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
uv->pcapfp = fdopen(fd, "wb");
|
||||
uefi_vars_pcap_header(uv->pcapfp);
|
||||
}
|
||||
|
||||
void uefi_vars_pcap_reset(uefi_vars_state *uv)
|
||||
{
|
||||
if (!uv->pcapfp) {
|
||||
return;
|
||||
}
|
||||
uefi_vars_pcap_packet(uv->pcapfp, TYPE_RESET, NULL, 0);
|
||||
}
|
||||
|
||||
void uefi_vars_pcap_request(uefi_vars_state *uv, void *buffer, size_t size)
|
||||
{
|
||||
if (!uv->pcapfp) {
|
||||
return;
|
||||
}
|
||||
uefi_vars_pcap_packet(uv->pcapfp, TYPE_REQUEST, buffer, size);
|
||||
}
|
||||
|
||||
void uefi_vars_pcap_reply(uefi_vars_state *uv, void *buffer, size_t size)
|
||||
{
|
||||
if (!uv->pcapfp) {
|
||||
return;
|
||||
}
|
||||
uefi_vars_pcap_packet(uv->pcapfp, TYPE_REPLY, buffer, size);
|
||||
}
|
||||
@@ -33,6 +33,7 @@ static const Property uefi_vars_sysbus_properties[] = {
|
||||
DEFINE_PROP_SIZE("size", uefi_vars_sysbus_state, state.max_storage,
|
||||
256 * 1024),
|
||||
DEFINE_PROP_STRING("jsonfile", uefi_vars_sysbus_state, state.jsonfile),
|
||||
DEFINE_PROP_STRING("pcapfile", uefi_vars_sysbus_state, state.pcapfile),
|
||||
DEFINE_PROP_BOOL("force-secure-boot", uefi_vars_sysbus_state,
|
||||
state.force_secure_boot, false),
|
||||
DEFINE_PROP_BOOL("disable-custom-mode", uefi_vars_sysbus_state,
|
||||
|
||||
@@ -77,6 +77,10 @@ struct uefi_vars_state {
|
||||
bool force_secure_boot;
|
||||
bool disable_custom_mode;
|
||||
bool use_pio;
|
||||
|
||||
/* request + reply capture */
|
||||
char *pcapfile;
|
||||
FILE *pcapfp;
|
||||
};
|
||||
|
||||
struct uefi_vars_cert {
|
||||
@@ -189,4 +193,10 @@ uefi_var_policy *uefi_vars_add_policy(uefi_vars_state *uv,
|
||||
variable_policy_entry *pe);
|
||||
uint32_t uefi_vars_mm_check_policy_proto(uefi_vars_state *uv);
|
||||
|
||||
/* vars-service-pcap.c */
|
||||
void uefi_vars_pcap_init(uefi_vars_state *uv, Error **errp);
|
||||
void uefi_vars_pcap_reset(uefi_vars_state *uv);
|
||||
void uefi_vars_pcap_request(uefi_vars_state *uv, void *buffer, size_t size);
|
||||
void uefi_vars_pcap_reply(uefi_vars_state *uv, void *buffer, size_t size);
|
||||
|
||||
#endif /* QEMU_UEFI_VAR_SERVICE_H */
|
||||
|
||||
Reference in New Issue
Block a user