aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/bhyve/fwctl.c36
1 files changed, 27 insertions, 9 deletions
diff --git a/usr.sbin/bhyve/fwctl.c b/usr.sbin/bhyve/fwctl.c
index 047a1050e7fd..1ed157fd9d48 100644
--- a/usr.sbin/bhyve/fwctl.c
+++ b/usr.sbin/bhyve/fwctl.c
@@ -67,12 +67,11 @@ __FBSDID("$FreeBSD$");
* Back-end state-machine
*/
static enum state {
- DORMANT,
IDENT_WAIT,
IDENT_SEND,
REQ,
RESP
-} be_state = DORMANT;
+} be_state;
static uint8_t sig[] = { 'B', 'H', 'Y', 'V' };
static u_int ident_idx;
@@ -200,6 +199,7 @@ static void
fget_data(uint32_t data, uint32_t len __unused)
{
+ assert(fget_cnt + sizeof(uint32_t) <= sizeof(fget_str));
memcpy(&fget_str[fget_cnt], &data, sizeof(data));
fget_cnt += sizeof(uint32_t);
}
@@ -344,7 +344,8 @@ static int
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
@@ -441,6 +442,28 @@ fwctl_response(uint32_t *retval)
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.
@@ -468,18 +491,13 @@ fwctl_inb(void)
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();
}
}