1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
|
--- usr.sbin/bhyve/fwctl.c.orig
+++ usr.sbin/bhyve/fwctl.c
@@ -66,13 +66,12 @@
/*
* Back-end state-machine
*/
-enum state {
- DORMANT,
+static enum state {
IDENT_WAIT,
IDENT_SEND,
REQ,
RESP
-} be_state = DORMANT;
+} be_state;
static uint8_t sig[] = { 'B', 'H', 'Y', 'V' };
static u_int ident_idx;
@@ -203,7 +202,8 @@
fget_data(uint32_t data, uint32_t len)
{
- *((uint32_t *) &fget_str[fget_cnt]) = data;
+ assert(fget_cnt + sizeof(uint32_t) <= sizeof(fget_str));
+ memcpy(&fget_str[fget_cnt], &data, sizeof(data));
fget_cnt += sizeof(uint32_t);
}
@@ -347,7 +347,8 @@
fwctl_request_data(uint32_t value)
{
- /* Make sure remaining size is >= 0 */
+ /* Make sure remaining size is > 0 */
+ assert(rinfo.req_size > 0);
if (rinfo.req_size <= sizeof(uint32_t))
rinfo.req_size = 0;
else
@@ -445,6 +446,28 @@
return (0);
}
+static void
+fwctl_reset(void)
+{
+
+ switch (be_state) {
+ case RESP:
+ /* If a response was generated but not fully read, discard it. */
+ fwctl_response_done();
+ break;
+ case REQ:
+ /* Discard partially-received request. */
+ memset(&rinfo, 0, sizeof(rinfo));
+ break;
+ case IDENT_WAIT:
+ case IDENT_SEND:
+ break;
+ }
+
+ be_state = IDENT_SEND;
+ ident_idx = 0;
+}
+
/*
* i/o port handling.
@@ -472,18 +495,13 @@
static void
fwctl_outw(uint16_t val)
{
- if (be_state == DORMANT) {
- return;
- }
-
if (val == 0) {
/*
* The guest wants to read the signature. It's possible that the
* guest is unaware of the fwctl state at this moment. For that
* reason, reset the state machine unconditionally.
*/
- be_state = IDENT_SEND;
- ident_idx = 0;
+ fwctl_reset();
}
}
|