master
c 95 lines 2.15 KB
Raw
1 /*
2 * SPDX-License-Identifier: GPL-2.0-or-later
3 */
4 #include "qemu/osdep.h"
5 #include "qemu/error-report.h"
6 #include "qemu/pcap.h"
7 #include "system/dma.h"
8
9 #include "hw/uefi/var-service.h"
10
11 #define LINKTYPE_EDK2_MM 302
12
13 #define SNAPLEN (64 * 1024)
14 #define TYPE_RESET 0x01
15 #define TYPE_REQUEST 0x02
16 #define TYPE_REPLY 0x03
17
18 static void uefi_vars_pcap_header(FILE *fp)
19 {
20 static const struct pcap_hdr header = {
21 .magic_number = PCAP_MAGIC,
22 .version_major = PCAP_MAJOR,
23 .version_minor = PCAP_MINOR,
24 .snaplen = SNAPLEN,
25 .network = LINKTYPE_EDK2_MM,
26 };
27
28 fwrite(&header, sizeof(header), 1, fp);
29 fflush(fp);
30 }
31
32 static void uefi_vars_pcap_packet(FILE *fp, uint32_t type,
33 void *buffer, size_t size)
34 {
35 struct pcaprec_hdr header;
36 struct timeval tv;
37 uint32_t orig_len = size + sizeof(type);
38 uint32_t incl_len = MIN(orig_len, SNAPLEN);
39
40 gettimeofday(&tv, NULL);
41 header.ts_sec = tv.tv_sec;
42 header.ts_usec = tv.tv_usec;
43 header.incl_len = incl_len;
44 header.orig_len = orig_len;
45
46 fwrite(&header, sizeof(header), 1, fp);
47 fwrite(&type, sizeof(type), 1, fp);
48 if (buffer) {
49 fwrite(buffer, incl_len - sizeof(type), 1, fp);
50 }
51 fflush(fp);
52 }
53
54 void uefi_vars_pcap_init(uefi_vars_state *uv, Error **errp)
55 {
56 int fd;
57
58 if (!uv->pcapfile) {
59 return;
60 }
61
62 fd = qemu_create(uv->pcapfile,
63 O_WRONLY | O_TRUNC | O_BINARY,
64 0666, errp);
65 if (fd < 0) {
66 return;
67 }
68
69 uv->pcapfp = fdopen(fd, "wb");
70 uefi_vars_pcap_header(uv->pcapfp);
71 }
72
73 void uefi_vars_pcap_reset(uefi_vars_state *uv)
74 {
75 if (!uv->pcapfp) {
76 return;
77 }
78 uefi_vars_pcap_packet(uv->pcapfp, TYPE_RESET, NULL, 0);
79 }
80
81 void uefi_vars_pcap_request(uefi_vars_state *uv, void *buffer, size_t size)
82 {
83 if (!uv->pcapfp) {
84 return;
85 }
86 uefi_vars_pcap_packet(uv->pcapfp, TYPE_REQUEST, buffer, size);
87 }
88
89 void uefi_vars_pcap_reply(uefi_vars_state *uv, void *buffer, size_t size)
90 {
91 if (!uv->pcapfp) {
92 return;
93 }
94 uefi_vars_pcap_packet(uv->pcapfp, TYPE_REPLY, buffer, size);
95 }