diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2012-10-21 12:47:59 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2012-10-21 12:47:59 +0000 |
commit | 0c31dce3a49b370f17a80f85dd5ad45812ddbe5c (patch) | |
tree | fad12ca0593667f26039b116ffc11f1c49c27f79 /usr.sbin | |
parent | da8b4e84412d585f87ceaf32cde56eb1e58669dd (diff) |
Add domain services support code and use it to fetch the PRI
(Physical Resource Inventory) from the service processor.
Diffstat (limited to 'usr.sbin')
-rw-r--r-- | usr.sbin/ldomctl/Makefile | 5 | ||||
-rw-r--r-- | usr.sbin/ldomctl/ds.c | 649 | ||||
-rw-r--r-- | usr.sbin/ldomctl/ds.h | 207 | ||||
-rw-r--r-- | usr.sbin/ldomctl/ldomctl.c | 133 |
4 files changed, 959 insertions, 35 deletions
diff --git a/usr.sbin/ldomctl/Makefile b/usr.sbin/ldomctl/Makefile index df268c563e8..cf0e9217fb9 100644 --- a/usr.sbin/ldomctl/Makefile +++ b/usr.sbin/ldomctl/Makefile @@ -1,8 +1,9 @@ -# $OpenBSD: Makefile,v 1.2 2012/10/15 20:28:50 kettenis Exp $ +# $OpenBSD: Makefile,v 1.3 2012/10/21 12:47:58 kettenis Exp $ PROG= ldomctl -SRCS= ldomctl.c mdesc.c +SRCS= ldomctl.c ds.c mdesc.c NOMAN= CFLAGS+= -Wall +DEBUG= -g .include <bsd.prog.mk> diff --git a/usr.sbin/ldomctl/ds.c b/usr.sbin/ldomctl/ds.c new file mode 100644 index 00000000000..27d3bfa35c6 --- /dev/null +++ b/usr.sbin/ldomctl/ds.c @@ -0,0 +1,649 @@ +/* $OpenBSD: ds.c,v 1.1 2012/10/21 12:47:58 kettenis Exp $ */ + +/* + * Copyright (c) 2012 Mark Kettenis + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/types.h> +#include <err.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "ds.h" +#include "mdesc.h" + +#define DPRINTF(x) printf x + +void pri_start(struct ldc_conn *, uint64_t); +void pri_rx_data(struct ldc_conn *, uint64_t, void *, size_t); + +struct ds_service ds_service[] = { + { "pri", 1, 0, pri_start, pri_rx_data }, + { NULL, 0, 0 } +}; + +#define min(a, b) ((a) < (b) ? (a) : (b)) +#define max(a, b) ((a) > (b) ? (a) : (b)) + +void ldc_rx_ctrl_vers(struct ldc_conn *, struct ldc_pkt *); +void ldc_rx_ctrl_rtr(struct ldc_conn *, struct ldc_pkt *); +void ldc_rx_ctrl_rts(struct ldc_conn *, struct ldc_pkt *); +void ldc_rx_ctrl_rdx(struct ldc_conn *, struct ldc_pkt *); + +void ldc_send_ack(struct ldc_conn *); +void ldc_send_rtr(struct ldc_conn *); +void ldc_send_rts(struct ldc_conn *); +void ldc_send_rdx(struct ldc_conn *); + +void +ldc_rx_ctrl(struct ldc_conn *lc, struct ldc_pkt *lp) +{ + switch (lp->ctrl) { + case LDC_VERS: + ldc_rx_ctrl_vers(lc, lp); + break; + + case LDC_RTS: + ldc_rx_ctrl_rts(lc, lp); + break; + + case LDC_RTR: + ldc_rx_ctrl_rtr(lc, lp); + break; + + case LDC_RDX: + ldc_rx_ctrl_rdx(lc, lp); + break; + + default: + DPRINTF(("CTRL/0x%02x/0x%02x\n", lp->stype, lp->ctrl)); + ldc_reset(lc); + break; + } +} + +void +ldc_rx_ctrl_vers(struct ldc_conn *lc, struct ldc_pkt *lp) +{ + struct ldc_pkt *lvp = (struct ldc_pkt *)lp; + + switch (lp->stype) { + case LDC_INFO: + if (lc->lc_state == LDC_RCV_VERS) { + DPRINTF(("Spurious CTRL/INFO/VERS: state %d\n", + lc->lc_state)); + return; + } + DPRINTF(("CTRL/INFO/VERS\n")); + if (lvp->major == LDC_VERSION_MAJOR && + lvp->minor == LDC_VERSION_MINOR) + ldc_send_ack(lc); + else + /* XXX do nothing for now. */ + ; + break; + + case LDC_ACK: + if (lc->lc_state != LDC_SND_VERS) { + DPRINTF(("Spurious CTRL/ACK/VERS: state %d\n", + lc->lc_state)); + ldc_reset(lc); + return; + } + DPRINTF(("CTRL/ACK/VERS\n")); + ldc_send_rts(lc); + break; + + case LDC_NACK: + DPRINTF(("CTRL/NACK/VERS\n")); + ldc_reset(lc); + break; + + default: + DPRINTF(("CTRL/0x%02x/VERS\n", lp->stype)); + ldc_reset(lc); + break; + } +} + +void +ldc_rx_ctrl_rts(struct ldc_conn *lc, struct ldc_pkt *lp) +{ + switch (lp->stype) { + case LDC_INFO: + if (lc->lc_state != LDC_RCV_VERS) { + DPRINTF(("Spurious CTRL/INFO/RTS: state %d\n", + lc->lc_state)); + ldc_reset(lc); + return; + } + DPRINTF(("CTRL/INFO/RTS\n")); + if (lp->env != LDC_MODE_RELIABLE) { + ldc_reset(lc); + return; + } + ldc_send_rtr(lc); + break; + + case LDC_ACK: + DPRINTF(("CTRL/ACK/RTS\n")); + ldc_reset(lc); + break; + + case LDC_NACK: + DPRINTF(("CTRL/NACK/RTS\n")); + ldc_reset(lc); + break; + + default: + DPRINTF(("CTRL/0x%02x/RTS\n", lp->stype)); + ldc_reset(lc); + break; + } +} + +void +ldc_rx_ctrl_rtr(struct ldc_conn *lc, struct ldc_pkt *lp) +{ + switch (lp->stype) { + case LDC_INFO: + if (lc->lc_state != LDC_SND_RTS) { + DPRINTF(("Spurious CTRL/INFO/RTR: state %d\n", + lc->lc_state)); + ldc_reset(lc); + return; + } + DPRINTF(("CTRL/INFO/RTR\n")); + if (lp->env != LDC_MODE_RELIABLE) { + ldc_reset(lc); + return; + } + ldc_send_rdx(lc); +#if 0 + lc->lc_start(lc); +#endif + break; + + case LDC_ACK: + DPRINTF(("CTRL/ACK/RTR\n")); + ldc_reset(lc); + break; + + case LDC_NACK: + DPRINTF(("CTRL/NACK/RTR\n")); + ldc_reset(lc); + break; + + default: + DPRINTF(("CTRL/0x%02x/RTR\n", lp->stype)); + ldc_reset(lc); + break; + } +} + +void +ldc_rx_ctrl_rdx(struct ldc_conn *lc, struct ldc_pkt *lp) +{ + switch (lp->stype) { + case LDC_INFO: + if (lc->lc_state != LDC_SND_RTR) { + DPRINTF(("Spurious CTRL/INFO/RTR: state %d\n", + lc->lc_state)); + ldc_reset(lc); + return; + } + DPRINTF(("CTRL/INFO/RDX\n")); +#if 0 + lc->lc_start(lc); +#endif + break; + + case LDC_ACK: + DPRINTF(("CTRL/ACK/RDX\n")); + ldc_reset(lc); + break; + + case LDC_NACK: + DPRINTF(("CTRL/NACK/RDX\n")); + ldc_reset(lc); + break; + + default: + DPRINTF(("CTRL/0x%02x/RDX\n", lp->stype)); + ldc_reset(lc); + break; + } +} + +void +ldc_rx_data(struct ldc_conn *lc, struct ldc_pkt *lp) +{ + size_t len; + + if (lp->stype != LDC_INFO && lp->stype != LDC_ACK) { + DPRINTF(("DATA/0x%02x\n", lp->stype)); + ldc_reset(lc); + return; + } + + if (lc->lc_state != LDC_SND_RTR && + lc->lc_state != LDC_SND_RDX) { + DPRINTF(("Spurious DATA/INFO: state %d\n", lc->lc_state)); + ldc_reset(lc); + return; + } + + if (lp->ackid) { + int i; + + for (i = 0; ds_service[i].ds_svc_id; i++) { + if (ds_service[i].ds_ackid && + lp->ackid >= ds_service[i].ds_ackid) { + ds_service[i].ds_ackid = 0; + ds_service[i].ds_start(lc, ds_service[i].ds_svc_handle); + } + } + } + if (lp->stype == LDC_ACK) + return; + + if (lp->env & LDC_FRAG_START) { + lc->lc_len = (lp->env & LDC_LEN_MASK); + memcpy((uint8_t *)lc->lc_msg, &lp->data, lc->lc_len); + } else { + len = (lp->env & LDC_LEN_MASK); + if (lc->lc_len + len > sizeof(lc->lc_msg)) { + DPRINTF(("Buffer overrun\n")); + ldc_reset(lc); + return; + } + memcpy((uint8_t *)lc->lc_msg + lc->lc_len, &lp->data, len); + lc->lc_len += len; + } + + if (lp->env & LDC_FRAG_STOP) { + ldc_ack(lc, lp->seqid); + lc->lc_rx_data(lc, lc->lc_msg, lc->lc_len); + } +} + +void +ldc_send_vers(struct ldc_conn *lc) +{ + struct ldc_pkt lp; + ssize_t nbytes; + + bzero(&lp, sizeof(lp)); + lp.type = LDC_CTRL; + lp.stype = LDC_INFO; + lp.ctrl = LDC_VERS; + lp.major = 1; + lp.minor = 0; + + nbytes = write(lc->lc_fd, &lp, sizeof(lp)); + if (nbytes != sizeof(lp)) + err(1, "write"); + + lc->lc_state = LDC_SND_VERS; +} + +void +ldc_send_ack(struct ldc_conn *lc) +{ + struct ldc_pkt lp; + ssize_t nbytes; + + bzero(&lp, sizeof(lp)); + lp.type = LDC_CTRL; + lp.stype = LDC_ACK; + lp.ctrl = LDC_VERS; + lp.major = 1; + lp.minor = 0; + + nbytes = write(lc->lc_fd, &lp, sizeof(lp)); + if (nbytes != sizeof(lp)) + err(1, "write"); + + lc->lc_state = LDC_RCV_VERS; +} + +void +ldc_send_rts(struct ldc_conn *lc) +{ + struct ldc_pkt lp; + ssize_t nbytes; + + bzero(&lp, sizeof(lp)); + lp.type = LDC_CTRL; + lp.stype = LDC_INFO; + lp.ctrl = LDC_RTS; + lp.env = LDC_MODE_RELIABLE; + lp.seqid = lc->lc_tx_seqid++; + + nbytes = write(lc->lc_fd, &lp, sizeof(lp)); + if (nbytes != sizeof(lp)) + err(1, "write"); + + lc->lc_state = LDC_SND_RTS; +} + +void +ldc_send_rtr(struct ldc_conn *lc) +{ + struct ldc_pkt lp; + ssize_t nbytes; + + bzero(&lp, sizeof(lp)); + lp.type = LDC_CTRL; + lp.stype = LDC_INFO; + lp.ctrl = LDC_RTR; + lp.env = LDC_MODE_RELIABLE; + lp.seqid = lc->lc_tx_seqid++; + + nbytes = write(lc->lc_fd, &lp, sizeof(lp)); + if (nbytes != sizeof(lp)) + err(1, "write"); + + lc->lc_state = LDC_SND_RTR; +} + +void +ldc_send_rdx(struct ldc_conn *lc) +{ + struct ldc_pkt lp; + ssize_t nbytes; + + bzero(&lp, sizeof(lp)); + lp.type = LDC_CTRL; + lp.stype = LDC_INFO; + lp.ctrl = LDC_RDX; + lp.env = LDC_MODE_RELIABLE; + lp.seqid = lc->lc_tx_seqid++; + + nbytes = write(lc->lc_fd, &lp, sizeof(lp)); + if (nbytes != sizeof(lp)) + err(1, "write"); + + lc->lc_state = LDC_SND_RDX; +} + +void +ldc_reset(struct ldc_conn *lc) +{ + abort(); + + lc->lc_tx_seqid = 0; + lc->lc_state = 0; +#if 0 + lc->lc_reset(lc); +#endif +} + +void +ldc_ack(struct ldc_conn *lc, uint32_t ackid) +{ + struct ldc_pkt lp; + ssize_t nbytes; + + bzero(&lp, sizeof(lp)); + lp.type = LDC_DATA; + lp.stype = LDC_ACK; + lp.seqid = lc->lc_tx_seqid++; + lp.ackid = ackid; + nbytes = write(lc->lc_fd, &lp, sizeof(lp)); + if (nbytes != sizeof(lp)) + err(1, "write"); +} + +void +ds_rx_msg(struct ldc_conn *lc, void *data, size_t len) +{ + struct ds_msg *dm = data; + + switch(dm->msg_type) { + case DS_INIT_REQ: + { + struct ds_init_req *dr = data; + + DPRINTF(("DS_INIT_REQ %d.%d\n", dr->major_vers, + dr->minor_vers)); + if (dr->major_vers != 1 || dr->minor_vers != 0){ + ldc_reset(lc); + return; + } + ds_init_ack(lc); + break; + } + + case DS_REG_REQ: + { + struct ds_reg_req *dr = data; + int i; + + DPRINTF(("DS_REG_REQ %s %d.%d 0x%016llx\n", dr->svc_id, + dr->major_vers, dr->minor_vers, dr->svc_handle)); + for (i = 0; ds_service[i].ds_svc_id; i++) + if (strcmp(dr->svc_id, ds_service[i].ds_svc_id) == 0) { + ds_service[i].ds_svc_handle = dr->svc_handle; + ds_service[i].ds_ackid = lc->lc_tx_seqid; + ds_reg_ack(lc, dr->svc_handle); + return; + } + + ds_reg_nack(lc, dr->svc_handle); + break; + } + + case DS_DATA: + { + struct ds_data *dd = data; + int i; + + DPRINTF(("DS_DATA 0x%016llx\n", dd->svc_handle)); + for (i = 0; ds_service[i].ds_svc_id; i++) + if (ds_service[i].ds_svc_handle == dd->svc_handle) + ds_service[i].ds_rx_data(lc, dd->svc_handle, + data, len); + break; + } + + default: + DPRINTF(("Unknown DS message type 0x%x\n", dm->msg_type)); + ldc_reset(lc); + break; + } +} + +void +ds_init_ack(struct ldc_conn *lc) +{ + struct ds_init_ack da; + + bzero(&da, sizeof(da)); + da.msg_type = DS_INIT_ACK; + da.payload_len = sizeof(da) - 8; + da.minor_vers = 0; + ds_send_msg(lc, &da, sizeof(da)); +} + +void +ds_reg_ack(struct ldc_conn *lc, uint64_t svc_handle) +{ + struct ds_reg_ack da; + + bzero(&da, sizeof(da)); + da.msg_type = DS_REG_ACK; + da.payload_len = sizeof(da) - 8; + da.svc_handle = svc_handle; + da.minor_vers = 0; + ds_send_msg(lc, &da, sizeof(da)); +} + +void +ds_reg_nack(struct ldc_conn *lc, uint64_t svc_handle) +{ + struct ds_reg_nack dn; + + bzero(&dn, sizeof(dn)); + dn.msg_type = DS_REG_NACK; + dn.payload_len = sizeof(dn) - 8; + dn.svc_handle = svc_handle; + dn.result = DS_REG_VER_NACK; + dn.major_vers = 0; + ds_send_msg(lc, &dn, sizeof(dn)); +} + +void +ds_receive_msg(struct ldc_conn *lc, void *buf, size_t len) +{ + int env = LDC_FRAG_START; + struct ldc_pkt lp; + uint8_t *p = buf; + ssize_t nbytes; + + while (len > 0) { + nbytes = read(lc->lc_fd, &lp, sizeof(lp)); + if (nbytes != sizeof(lp)) + err(1, "read"); + + if (lp.type != LDC_DATA && + lp.stype != LDC_INFO) { + ldc_reset(lc); + return; + } + + if ((lp.env & LDC_FRAG_START) != env) { + ldc_reset(lc); + return; + } + + bcopy(&lp.data, p, (lp.env & LDC_LEN_MASK)); + p += (lp.env & LDC_LEN_MASK); + len -= (lp.env & LDC_LEN_MASK); + + if (lp.env & LDC_FRAG_STOP) + ldc_ack(lc, lp.seqid); + + env = (lp.env & LDC_FRAG_STOP) ? LDC_FRAG_START : 0; + } +} + +void +ldc_send_msg(struct ldc_conn *lc, void *buf, size_t len) +{ + struct ldc_pkt lp; + uint8_t *p = buf; + ssize_t nbytes; + + while (len > 0) { + bzero(&lp, sizeof(lp)); + lp.type = LDC_DATA; + lp.stype = LDC_INFO; + lp.env = min(len, LDC_PKT_PAYLOAD); + if (p == buf) + lp.env |= LDC_FRAG_START; + if (len <= LDC_PKT_PAYLOAD) + lp.env |= LDC_FRAG_STOP; + lp.seqid = lc->lc_tx_seqid++; + bcopy(p, &lp.data, min(len, LDC_PKT_PAYLOAD)); + + nbytes = write(lc->lc_fd, &lp, sizeof(lp)); + if (nbytes != sizeof(lp)) + err(1, "write"); + p += min(len, LDC_PKT_PAYLOAD); + len -= min(len, LDC_PKT_PAYLOAD); + } +} + +void +ds_send_msg(struct ldc_conn *lc, void *buf, size_t len) +{ + uint8_t *p = buf; +#if 0 + struct ldc_pkt lp; + ssize_t nbytes; +#endif + + while (len > 0) { + ldc_send_msg(lc, p, min(len, LDC_MSG_MAX)); + p += min(len, LDC_MSG_MAX); + len -= min(len, LDC_MSG_MAX); + +#if 0 + /* Consume ACK. */ + nbytes = read(lc->lc_fd, &lp, sizeof(lp)); + if (nbytes != sizeof(lp)) + err(1, "read"); + + { + uint64_t *msg = (uint64_t *)&lp; + int i; + + for (i = 0; i < 8; i++) + printf("%02x: %016llx\n", i, msg[i]); + } +#endif + } +} + +struct pri_msg { + uint32_t msg_type; + uint32_t payload_len; + uint64_t svc_handle; + uint64_t reqnum; + uint64_t type; +} __packed; + +struct pri_data { + uint32_t msg_type; + uint32_t payload_len; + uint64_t svc_handle; + uint64_t reqnum; + uint64_t type; + char data[1]; +} __packed; + +void +pri_start(struct ldc_conn *lc, uint64_t svc_handle) +{ + struct pri_msg pm; + + bzero(&pm, sizeof(pm)); + pm.msg_type = DS_DATA; + pm.payload_len = sizeof(pm) - 8; + pm.svc_handle = svc_handle; + pm.reqnum = 0; + pm.type = 0; + ds_send_msg(lc, &pm, sizeof(pm)); +} + +void *pri_buf; +size_t pri_len; + +void +pri_rx_data(struct ldc_conn *lc, uint64_t svc_handle, void *data, size_t len) +{ + struct pri_data *pd = data; + + pri_len = pd->payload_len - 24; + pri_buf = xmalloc(pri_len); + + len -= sizeof(struct pri_msg); + bcopy(&pd->data, pri_buf, len); + ds_receive_msg(lc, pri_buf + len, pri_len - len); +} diff --git a/usr.sbin/ldomctl/ds.h b/usr.sbin/ldomctl/ds.h new file mode 100644 index 00000000000..121528dc7f8 --- /dev/null +++ b/usr.sbin/ldomctl/ds.h @@ -0,0 +1,207 @@ +/* $OpenBSD: ds.h,v 1.1 2012/10/21 12:47:58 kettenis Exp $ */ + +/* + * Copyright (c) 2012 Mark Kettenis + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/types.h> + +/* + * LDC virtual link layer protocol. + */ + +#define LDC_VERSION_MAJOR 1 +#define LDC_VERSION_MINOR 0 + +#define LDC_PKT_PAYLOAD 48 + +struct ldc_pkt { + uint8_t type; + uint8_t stype; + uint8_t ctrl; + uint8_t env; + uint32_t seqid; + + uint16_t major; + uint16_t minor; + uint32_t ackid; + + uint64_t data[6]; +}; + +/* Packet types. */ +#define LDC_CTRL 0x01 +#define LDC_DATA 0x02 +#define LDC_ERR 0x10 + +/* Packet subtypes. */ +#define LDC_INFO 0x01 +#define LDC_ACK 0x02 +#define LDC_NACK 0x04 + +/* Control info values. */ +#define LDC_VERS 0x01 +#define LDC_RTS 0x02 +#define LDC_RTR 0x03 +#define LDC_RDX 0x04 + +/* Packet envelope. */ +#define LDC_MODE_RAW 0x00 +#define LDC_MODE_UNRELIABLE 0x01 +#define LDC_MODE_RELIABLE 0x03 + +#define LDC_LEN_MASK 0x3f +#define LDC_FRAG_MASK 0xc0 +#define LDC_FRAG_START 0x40 +#define LDC_FRAG_STOP 0x80 + +#define LDC_MSG_MAX 4096 + +struct ldc_conn { + int lc_fd; + + uint32_t lc_tx_seqid; + uint8_t lc_state; +#define LDC_SND_VERS 1 +#define LDC_RCV_VERS 2 +#define LDC_SND_RTS 3 +#define LDC_SND_RTR 4 +#define LDC_SND_RDX 5 + + uint64_t lc_msg[LDC_MSG_MAX / 8]; + size_t lc_len; + + void (*lc_reset)(struct ldc_conn *); + void (*lc_start)(struct ldc_conn *); + void (*lc_rx_data)(struct ldc_conn *, void *, size_t); +}; + +void ldc_rx_ctrl(struct ldc_conn *, struct ldc_pkt *); +void ldc_rx_data(struct ldc_conn *, struct ldc_pkt *); + +void ldc_send_vers(struct ldc_conn *); + +void ldc_reset(struct ldc_conn *); + +struct ds_msg { + uint32_t msg_type; + uint32_t payload_len; + uint64_t data[5]; +}; + +struct ds_init_req { + uint32_t msg_type; + uint32_t payload_len; + uint16_t major_vers; + uint16_t minor_vers; +} __packed; + +struct ds_init_ack { + uint32_t msg_type; + uint32_t payload_len; + uint16_t minor_vers; +} __packed; + +#define DS_INIT_REQ 0x00 +#define DS_INIT_ACK 0x01 +#define DS_INIT_NACK 0x02 + +struct ds_reg_req { + uint32_t msg_type; + uint32_t payload_len; + uint64_t svc_handle; + uint16_t major_vers; + uint16_t minor_vers; + char svc_id[1]; +} __packed; + +#define DS_REG_REQ 0x03 + +struct ds_reg_ack { + uint32_t msg_type; + uint32_t payload_len; + uint64_t svc_handle; + uint16_t minor_vers; + uint8_t _reserved[6]; +} __packed; + +#define DS_REG_ACK 0x04 + +struct ds_reg_nack { + uint32_t msg_type; + uint32_t payload_len; + uint64_t svc_handle; + uint64_t result; + uint16_t major_vers; + uint8_t _reserved[6]; +} __packed; + +#define DS_REG_NACK 0x05 + +struct ds_unreg { + uint32_t msg_type; + uint32_t payload_len; + uint64_t svc_handle; +} __packed; + +#define DS_UNREG 0x06 +#define DS_UNREG_ACK 0x07 +#define DS_UNREG_NACK 0x08 + +struct ds_data { + uint32_t msg_type; + uint32_t payload_len; + uint64_t svc_handle; + uint64_t data[4]; +}; + +#define DS_DATA 0x09 + +struct ds_nack { + uint32_t msg_type; + uint32_t payload_len; + uint64_t svc_handle; + uint64_t result; +} __packed; + +#define DS_NACK 0x0a + +#define DS_REG_VER_NACK 0x01 +#define DS_REG_DUP 0x02 +#define DS_INV_HDL 0x03 +#define DS_TYPE_UNKNOWN 0x04 + +struct ds_service { + const char *ds_svc_id; + uint16_t ds_major_vers; + uint16_t ds_minor_vers; + + void (*ds_start)(struct ldc_conn *, uint64_t); + void (*ds_rx_data)(struct ldc_conn *, uint64_t, void *, + size_t); + + uint64_t ds_svc_handle; + uint32_t ds_ackid; +}; + +void ldc_ack(struct ldc_conn *, uint32_t); +void ds_rx_msg(struct ldc_conn *, void *, size_t); + +void ds_init_ack(struct ldc_conn *); +void ds_reg_ack(struct ldc_conn *, uint64_t); +void ds_reg_nack(struct ldc_conn *, uint64_t); + +void ds_receive_msg(struct ldc_conn *lc, void *, size_t); +void ds_send_msg(struct ldc_conn *lc, void *, size_t); diff --git a/usr.sbin/ldomctl/ldomctl.c b/usr.sbin/ldomctl/ldomctl.c index 431dfe6c0ec..78521976215 100644 --- a/usr.sbin/ldomctl/ldomctl.c +++ b/usr.sbin/ldomctl/ldomctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ldomctl.c,v 1.6 2012/10/20 16:44:16 kettenis Exp $ */ +/* $OpenBSD: ldomctl.c,v 1.7 2012/10/21 12:47:58 kettenis Exp $ */ /* * Copyright (c) 2012 Mark Kettenis @@ -25,8 +25,11 @@ #include <string.h> #include <unistd.h> +#include "ds.h" #include "mdesc.h" +#define DPRINTF(x) printf x + struct hv_io { uint64_t hi_cookie; void *hi_addr; @@ -146,6 +149,8 @@ TAILQ_HEAD(guest_head, guest) guests; void add_guest(struct md_node *); uint64_t find_guest(const char *); +void fetch_pri(void); + void dump(int argc, char **argv); void guest_start(int argc, char **argv); void guest_stop(int argc, char **argv); @@ -159,13 +164,16 @@ struct command commands[] = { { NULL, NULL } }; -int seq = 1; -int fd; +int hvctl_seq = 1; +int hvctl_fd; void *hvmd_buf; size_t hvmd_len; struct md *hvmd; +extern void *pri_buf; +extern size_t pri_len; + int main(int argc, char **argv) { @@ -191,22 +199,22 @@ main(int argc, char **argv) if (cmdp->cmd_name == NULL) usage(); - fd = open("/dev/hvctl", O_RDWR, 0); - if (fd == -1) + hvctl_fd = open("/dev/hvctl", O_RDWR, 0); + if (hvctl_fd == -1) err(1, "open"); /* * Say "Hello". */ bzero(&msg, sizeof(msg)); - msg.hdr.seq = seq++; + msg.hdr.seq = hvctl_seq++; msg.msg.hello.major = 1; - nbytes = write(fd, &msg, sizeof(msg)); + nbytes = write(hvctl_fd, &msg, sizeof(msg)); if (nbytes != sizeof(msg)) err(1, "write"); bzero(&msg, sizeof(msg)); - nbytes = read(fd, &msg, sizeof(msg)); + nbytes = read(hvctl_fd, &msg, sizeof(msg)); if (nbytes != sizeof(msg)) err(1, "read"); @@ -217,14 +225,14 @@ main(int argc, char **argv) */ bzero(&msg, sizeof(msg)); msg.hdr.op = 2; - msg.hdr.seq = seq++; + msg.hdr.seq = hvctl_seq++; msg.msg.clnge.code = code ^ 0x12cafe42a; - nbytes = write(fd, &msg, sizeof(msg)); + nbytes = write(hvctl_fd, &msg, sizeof(msg)); if (nbytes != sizeof(msg)) err(1, "write"); bzero(&msg, sizeof(msg)); - nbytes = read(fd, &msg, sizeof(msg)); + nbytes = read(hvctl_fd, &msg, sizeof(msg)); if (nbytes != sizeof(msg)) err(1, "read"); @@ -233,13 +241,13 @@ main(int argc, char **argv) */ bzero(&msg, sizeof(msg)); msg.hdr.op = HVCTL_OP_GET_HVCONFIG; - msg.hdr.seq = seq++; - nbytes = write(fd, &msg, sizeof(msg)); + msg.hdr.seq = hvctl_seq++; + nbytes = write(hvctl_fd, &msg, sizeof(msg)); if (nbytes != sizeof(msg)) err(1, "write"); bzero(&msg, sizeof(msg)); - nbytes = read(fd, &msg, sizeof(msg)); + nbytes = read(hvctl_fd, &msg, sizeof(msg)); if (nbytes != sizeof(msg)) err(1, "read"); @@ -247,7 +255,7 @@ main(int argc, char **argv) hi.hi_addr = &hdr; hi.hi_len = sizeof(hdr); - if (ioctl(fd, HVIOCREAD, &hi) == -1) + if (ioctl(hvctl_fd, HVIOCREAD, &hi) == -1) err(1, "ioctl"); hvmd_len = sizeof(hdr) + hdr.node_blk_sz + hdr.name_blk_sz + @@ -258,7 +266,7 @@ main(int argc, char **argv) hi.hi_addr = hvmd_buf; hi.hi_len = hvmd_len; - if (ioctl(fd, HVIOCREAD, &hi) == -1) + if (ioctl(hvctl_fd, HVIOCREAD, &hi) == -1) err(1, "ioctl"); hvmd = md_ingest(hvmd_buf, hvmd_len); @@ -328,6 +336,57 @@ find_guest(const char *name) } void +fetch_pri(void) +{ + struct ldc_conn lc; + ssize_t nbytes; + int fd; + + fd = open("/dev/spds", O_RDWR, 0); + if (fd == -1) + err(1, "open"); + + memset(&lc, 0, sizeof(lc)); + lc.lc_fd = fd; + lc.lc_rx_data = ds_rx_msg; + + while (pri_buf == NULL) { + struct ldc_pkt lp; + + bzero(&lp, sizeof(lp)); + nbytes = read(fd, &lp, sizeof(lp)); + if (nbytes != sizeof(lp)) + err(1, "read"); + +#if 0 + { + uint64_t *msg = (uint64_t *)&lp; + int i; + + for (i = 0; i < 8; i++) + printf("%02x: %016llx\n", i, msg[i]); + } +#endif + + switch (lp.type) { + case LDC_CTRL: + ldc_rx_ctrl(&lc, &lp); + break; + case LDC_DATA: + ldc_rx_data(&lc, &lp); + break; + default: + DPRINTF(("%0x02/%0x02/%0x02\n", lp.type, lp.stype, + lp.ctrl)); + ldc_reset(&lc); + break; + } + } + + close(fd); +} + +void dump(int argc, char **argv) { struct guest *guest; @@ -347,12 +406,20 @@ dump(int argc, char **argv) fwrite(hvmd_buf, hvmd_len, 1, fp); fclose(fp); + fetch_pri(); + + fp = fopen("pri", "w"); + if (fp == NULL) + err(1, "fopen"); + fwrite(pri_buf, pri_len, 1, fp); + fclose(fp); + TAILQ_FOREACH(guest, &guests, link) { hi.hi_cookie = guest->mdpa; hi.hi_addr = &hdr; hi.hi_len = sizeof(hdr); - if (ioctl(fd, HVIOCREAD, &hi) == -1) + if (ioctl(hvctl_fd, HVIOCREAD, &hi) == -1) err(1, "ioctl"); md_len = sizeof(hdr) + hdr.node_blk_sz + hdr.name_blk_sz + @@ -363,7 +430,7 @@ dump(int argc, char **argv) hi.hi_addr = md_buf; hi.hi_len = md_len; - if (ioctl(fd, HVIOCREAD, &hi) == -1) + if (ioctl(hvctl_fd, HVIOCREAD, &hi) == -1) err(1, "ioctl"); if (asprintf(&name, "%s.md", guest->name) == -1) @@ -394,14 +461,14 @@ guest_start(int argc, char **argv) */ bzero(&msg, sizeof(msg)); msg.hdr.op = HVCTL_OP_GUEST_START; - msg.hdr.seq = seq++; + msg.hdr.seq = hvctl_seq++; msg.msg.guestop.guestid = find_guest(argv[1]); - nbytes = write(fd, &msg, sizeof(msg)); + nbytes = write(hvctl_fd, &msg, sizeof(msg)); if (nbytes != sizeof(msg)) err(1, "write"); bzero(&msg, sizeof(msg)); - nbytes = read(fd, &msg, sizeof(msg)); + nbytes = read(hvctl_fd, &msg, sizeof(msg)); if (nbytes != sizeof(msg)) err(1, "read"); } @@ -420,14 +487,14 @@ guest_stop(int argc, char **argv) */ bzero(&msg, sizeof(msg)); msg.hdr.op = HVCTL_OP_GUEST_STOP; - msg.hdr.seq = seq++; + msg.hdr.seq = hvctl_seq++; msg.msg.guestop.guestid = find_guest(argv[1]); - nbytes = write(fd, &msg, sizeof(msg)); + nbytes = write(hvctl_fd, &msg, sizeof(msg)); if (nbytes != sizeof(msg)) err(1, "write"); bzero(&msg, sizeof(msg)); - nbytes = read(fd, &msg, sizeof(msg)); + nbytes = read(hvctl_fd, &msg, sizeof(msg)); if (nbytes != sizeof(msg)) err(1, "read"); } @@ -461,16 +528,16 @@ guest_status(int argc, char **argv) */ bzero(&msg, sizeof(msg)); msg.hdr.op = HVCTL_OP_GET_RES_STAT; - msg.hdr.seq = seq++; + msg.hdr.seq = hvctl_seq++; msg.msg.resstat.res = HVCTL_RES_GUEST; msg.msg.resstat.resid = guest->gid; msg.msg.resstat.infoid = HVCTL_INFO_GUEST_STATE; - nbytes = write(fd, &msg, sizeof(msg)); + nbytes = write(hvctl_fd, &msg, sizeof(msg)); if (nbytes != sizeof(msg)) err(1, "write"); bzero(&msg, sizeof(msg)); - nbytes = read(fd, &msg, sizeof(msg)); + nbytes = read(hvctl_fd, &msg, sizeof(msg)); if (nbytes != sizeof(msg)) err(1, "read"); @@ -487,16 +554,16 @@ guest_status(int argc, char **argv) bzero(&msg, sizeof(msg)); msg.hdr.op = HVCTL_OP_GET_RES_STAT; - msg.hdr.seq = seq++; + msg.hdr.seq = hvctl_seq++; msg.msg.resstat.res = HVCTL_RES_GUEST; msg.msg.resstat.resid = guest->gid; msg.msg.resstat.infoid = HVCTL_INFO_GUEST_SOFT_STATE; - nbytes = write(fd, &msg, sizeof(msg)); + nbytes = write(hvctl_fd, &msg, sizeof(msg)); if (nbytes != sizeof(msg)) err(1, "write"); bzero(&msg, sizeof(msg)); - nbytes = read(fd, &msg, sizeof(msg)); + nbytes = read(hvctl_fd, &msg, sizeof(msg)); if (nbytes != sizeof(msg)) err(1, "read"); @@ -505,16 +572,16 @@ guest_status(int argc, char **argv) bzero(&msg, sizeof(msg)); msg.hdr.op = HVCTL_OP_GET_RES_STAT; - msg.hdr.seq = seq++; + msg.hdr.seq = hvctl_seq++; msg.msg.resstat.res = HVCTL_RES_GUEST; msg.msg.resstat.resid = guest->gid; msg.msg.resstat.infoid = HVCTL_INFO_GUEST_UTILISATION; - nbytes = write(fd, &msg, sizeof(msg)); + nbytes = write(hvctl_fd, &msg, sizeof(msg)); if (nbytes != sizeof(msg)) err(1, "write"); bzero(&msg, sizeof(msg)); - nbytes = read(fd, &msg, sizeof(msg)); + nbytes = read(hvctl_fd, &msg, sizeof(msg)); if (nbytes != sizeof(msg)) err(1, "read"); |