summaryrefslogtreecommitdiff
path: root/usr.sbin
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2012-10-21 12:47:59 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2012-10-21 12:47:59 +0000
commit0c31dce3a49b370f17a80f85dd5ad45812ddbe5c (patch)
treefad12ca0593667f26039b116ffc11f1c49c27f79 /usr.sbin
parentda8b4e84412d585f87ceaf32cde56eb1e58669dd (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/Makefile5
-rw-r--r--usr.sbin/ldomctl/ds.c649
-rw-r--r--usr.sbin/ldomctl/ds.h207
-rw-r--r--usr.sbin/ldomctl/ldomctl.c133
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");