Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys add a port of the VMware Tools driver vmt(4) from OpenBSD
details: https://anonhg.NetBSD.org/src/rev/fc961de57692
branches: trunk
changeset: 770455:fc961de57692
user: jmcneill <jmcneill%NetBSD.org@localhost>
date: Mon Oct 17 22:39:22 2011 +0000
description:
add a port of the VMware Tools driver vmt(4) from OpenBSD
diffstat:
sys/arch/x86/conf/files.x86 | 6 +-
sys/arch/x86/x86/vmt.c | 1195 +++++++++++++++++++++++++++++++++++++++++++
sys/modules/vmt/Makefile | 14 +
sys/modules/vmt/vmt.ioconf | 10 +
4 files changed, 1224 insertions(+), 1 deletions(-)
diffs (truncated from 1251 to 300 lines):
diff -r 495f306310b5 -r fc961de57692 sys/arch/x86/conf/files.x86
--- a/sys/arch/x86/conf/files.x86 Mon Oct 17 22:38:01 2011 +0000
+++ b/sys/arch/x86/conf/files.x86 Mon Oct 17 22:39:22 2011 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: files.x86,v 1.72 2011/08/29 22:46:56 dyoung Exp $
+# $NetBSD: files.x86,v 1.73 2011/10/17 22:39:22 jmcneill Exp $
# options for MP configuration through the MP spec
defflag opt_mpbios.h MPBIOS MPVERBOSE MPDEBUG MPBIOS_SCANPCI
@@ -61,6 +61,10 @@
attach viac7temp at cpufeaturebus
file arch/x86/x86/viac7temp.c viac7temp
+device vmt: sysmon_power
+attach vmt at cpufeaturebus
+file arch/x86/x86/vmt.c vmt
+
file arch/x86/x86/apic.c ioapic | lapic
file arch/x86/x86/bus_dma.c
file arch/x86/x86/bus_space.c
diff -r 495f306310b5 -r fc961de57692 sys/arch/x86/x86/vmt.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/arch/x86/x86/vmt.c Mon Oct 17 22:39:22 2011 +0000
@@ -0,0 +1,1195 @@
+/* $NetBSD: vmt.c,v 1.1 2011/10/17 22:39:23 jmcneill Exp $ */
+/* $OpenBSD: vmt.c,v 1.11 2011/01/27 21:29:25 dtucker Exp $ */
+
+/*
+ * Copyright (c) 2007 David Crawshaw <david%zentus.com@localhost>
+ * Copyright (c) 2008 David Gwynne <dlg%openbsd.org@localhost>
+ *
+ * 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.
+ */
+
+/*
+ * Protocol reverse engineered by Ken Kato:
+ * http://chitchat.at.infoseek.co.jp/vmware/backdoor.html
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <sys/types.h>
+#include <sys/kmem.h>
+#include <sys/callout.h>
+#include <sys/reboot.h>
+#include <sys/syslog.h>
+#include <sys/proc.h>
+#include <sys/socket.h>
+#include <sys/module.h>
+
+#include <net/if.h>
+#include <netinet/in.h>
+
+#include <machine/cpuvar.h>
+
+#include <dev/sysmon/sysmonvar.h>
+#include <dev/sysmon/sysmon_taskq.h>
+
+/* #define VMT_DEBUG */
+
+/* "The" magic number, always occupies the EAX register. */
+#define VM_MAGIC 0x564D5868
+
+/* Port numbers, passed on EDX.LOW . */
+#define VM_PORT_CMD 0x5658
+#define VM_PORT_RPC 0x5659
+
+/* Commands, passed on ECX.LOW. */
+#define VM_CMD_GET_SPEED 0x01
+#define VM_CMD_APM 0x02
+#define VM_CMD_GET_MOUSEPOS 0x04
+#define VM_CMD_SET_MOUSEPOS 0x05
+#define VM_CMD_GET_CLIPBOARD_LEN 0x06
+#define VM_CMD_GET_CLIPBOARD 0x07
+#define VM_CMD_SET_CLIPBOARD_LEN 0x08
+#define VM_CMD_SET_CLIPBOARD 0x09
+#define VM_CMD_GET_VERSION 0x0a
+#define VM_VERSION_UNMANAGED 0x7fffffff
+#define VM_CMD_GET_DEVINFO 0x0b
+#define VM_CMD_DEV_ADDREMOVE 0x0c
+#define VM_CMD_GET_GUI_OPTIONS 0x0d
+#define VM_CMD_SET_GUI_OPTIONS 0x0e
+#define VM_CMD_GET_SCREEN_SIZE 0x0f
+#define VM_CMD_GET_HWVER 0x11
+#define VM_CMD_POPUP_OSNOTFOUND 0x12
+#define VM_CMD_GET_BIOS_UUID 0x13
+#define VM_CMD_GET_MEM_SIZE 0x14
+/*#define VM_CMD_GET_TIME 0x17 */ /* deprecated */
+#define VM_CMD_RPC 0x1e
+#define VM_CMD_GET_TIME_FULL 0x2e
+
+/* RPC sub-commands, passed on ECX.HIGH. */
+#define VM_RPC_OPEN 0x00
+#define VM_RPC_SET_LENGTH 0x01
+#define VM_RPC_SET_DATA 0x02
+#define VM_RPC_GET_LENGTH 0x03
+#define VM_RPC_GET_DATA 0x04
+#define VM_RPC_GET_END 0x05
+#define VM_RPC_CLOSE 0x06
+
+/* RPC magic numbers, passed on EBX. */
+#define VM_RPC_OPEN_RPCI 0x49435052UL /* with VM_RPC_OPEN. */
+#define VM_RPC_OPEN_TCLO 0x4F4C4354UL /* with VP_RPC_OPEN. */
+#define VM_RPC_ENH_DATA 0x00010000UL /* with enhanced RPC data calls. */
+
+#define VM_RPC_FLAG_COOKIE 0x80000000UL
+
+/* RPC reply flags */
+#define VM_RPC_REPLY_SUCCESS 0x0001
+#define VM_RPC_REPLY_DORECV 0x0002 /* incoming message available */
+#define VM_RPC_REPLY_CLOSED 0x0004 /* RPC channel is closed */
+#define VM_RPC_REPLY_UNSENT 0x0008 /* incoming message was removed? */
+#define VM_RPC_REPLY_CHECKPOINT 0x0010 /* checkpoint occurred -> retry */
+#define VM_RPC_REPLY_POWEROFF 0x0020 /* underlying device is powering off */
+#define VM_RPC_REPLY_TIMEOUT 0x0040
+#define VM_RPC_REPLY_HB 0x0080 /* high-bandwidth tx/rx available */
+
+/* VM state change IDs */
+#define VM_STATE_CHANGE_HALT 1
+#define VM_STATE_CHANGE_REBOOT 2
+#define VM_STATE_CHANGE_POWERON 3
+#define VM_STATE_CHANGE_RESUME 4
+#define VM_STATE_CHANGE_SUSPEND 5
+
+/* VM guest info keys */
+#define VM_GUEST_INFO_DNS_NAME 1
+#define VM_GUEST_INFO_IP_ADDRESS 2
+#define VM_GUEST_INFO_DISK_FREE_SPACE 3
+#define VM_GUEST_INFO_BUILD_NUMBER 4
+#define VM_GUEST_INFO_OS_NAME_FULL 5
+#define VM_GUEST_INFO_OS_NAME 6
+#define VM_GUEST_INFO_UPTIME 7
+#define VM_GUEST_INFO_MEMORY 8
+#define VM_GUEST_INFO_IP_ADDRESS_V2 9
+
+/* RPC responses */
+#define VM_RPC_REPLY_OK "OK "
+#define VM_RPC_RESET_REPLY "OK ATR toolbox"
+#define VM_RPC_REPLY_ERROR "ERROR Unknown command"
+#define VM_RPC_REPLY_ERROR_IP_ADDR "ERROR Unable to find guest IP address"
+
+/* A register. */
+union vm_reg {
+ struct {
+ uint16_t low;
+ uint16_t high;
+ } part;
+ uint32_t word;
+#ifdef __amd64__
+ struct {
+ uint32_t low;
+ uint32_t high;
+ } words;
+ uint64_t quad;
+#endif
+} __packed;
+
+/* A register frame. */
+struct vm_backdoor {
+ union vm_reg eax;
+ union vm_reg ebx;
+ union vm_reg ecx;
+ union vm_reg edx;
+ union vm_reg esi;
+ union vm_reg edi;
+ union vm_reg ebp;
+} __packed;
+
+/* RPC context. */
+struct vm_rpc {
+ uint16_t channel;
+ uint32_t cookie1;
+ uint32_t cookie2;
+};
+
+static int vmt_match(device_t, cfdata_t, void *);
+static void vmt_attach(device_t, device_t, void *);
+static int vmt_detach(device_t, int);
+
+struct vmt_softc {
+ device_t sc_dev;
+
+ struct vm_rpc sc_tclo_rpc;
+ bool sc_tclo_rpc_open;
+ char *sc_rpc_buf;
+ int sc_rpc_error;
+ int sc_tclo_ping;
+ int sc_set_guest_os;
+#define VMT_RPC_BUFLEN 256
+
+ struct callout sc_tick;
+ struct callout sc_tclo_tick;
+#if notyet
+ struct ksensordev sc_sensordev;
+ struct ksensor sc_sensor;
+#endif
+
+ struct sysmon_pswitch sc_smpsw_power;
+ struct sysmon_pswitch sc_smpsw_reset;
+ bool sc_smpsw_valid;
+
+ char sc_hostname[MAXHOSTNAMELEN];
+};
+
+CFATTACH_DECL_NEW(vmt, sizeof(struct vmt_softc),
+ vmt_match, vmt_attach, vmt_detach, NULL);
+
+static void vm_cmd(struct vm_backdoor *);
+static void vm_ins(struct vm_backdoor *);
+static void vm_outs(struct vm_backdoor *);
+
+/* Functions for communicating with the VM Host. */
+static int vm_rpc_open(struct vm_rpc *, uint32_t);
+static int vm_rpc_close(struct vm_rpc *);
+static int vm_rpc_send(const struct vm_rpc *, const uint8_t *, uint32_t);
+static int vm_rpc_send_str(const struct vm_rpc *, const uint8_t *);
+static int vm_rpc_get_length(const struct vm_rpc *, uint32_t *, uint16_t *);
+static int vm_rpc_get_data(const struct vm_rpc *, char *, uint32_t, uint16_t);
+static int vm_rpc_send_rpci_tx_buf(struct vmt_softc *, const uint8_t *, uint32_t);
+static int vm_rpc_send_rpci_tx(struct vmt_softc *, const char *, ...)
+ __printflike(2, 3);
+static int vm_rpci_response_successful(struct vmt_softc *);
+
+static void vmt_tclo_state_change_success(struct vmt_softc *, int, char);
+static void vmt_do_reboot(struct vmt_softc *);
+static void vmt_do_shutdown(struct vmt_softc *);
+
+static void vmt_update_guest_info(struct vmt_softc *);
+static void vmt_update_guest_uptime(struct vmt_softc *);
+
+static void vmt_tick(void *);
+static void vmt_tclo_tick(void *);
+static bool vmt_shutdown(device_t, int);
+static void vmt_pswitch_event(void *);
+
+extern char hostname[MAXHOSTNAMELEN];
+
+static bool
+vmt_probe(uint32_t *type)
+{
+ struct vm_backdoor frame;
+
+ memset(&frame, 0, sizeof(frame));
+
+ frame.eax.word = VM_MAGIC;
+ frame.ebx.word = ~VM_MAGIC;
+ frame.ecx.part.low = VM_CMD_GET_VERSION;
+ frame.ecx.part.high = 0xffff;
+ frame.edx.part.low = VM_PORT_CMD;
+ frame.edx.part.high = 0;
+
+ vm_cmd(&frame);
+
+ if (frame.eax.word == 0xffffffff ||
+ frame.ebx.word != VM_MAGIC)
+ return false;
+
+ if (type)
+ *type = frame.ecx.word;
+
+ return true;
+}
+
+static int
+vmt_match(device_t parent, cfdata_t match, void *aux)
+{
+ struct cpufeature_attach_args *cfaa = aux;
+ struct cpu_info *ci = cfaa->ci;
+
+ if (strcmp(cfaa->name, "vm") != 0)
+ return 0;
+ if ((ci->ci_flags & (CPUF_BSP|CPUF_SP|CPUF_PRIMARY)) == 0)
+ return 0;
+
+ return vmt_probe(NULL);
+}
+
+static const char *
+vmt_type(void)
+{
+ uint32_t vmwaretype = 0;
+
+ vmt_probe(&vmwaretype);
+
+ switch (vmwaretype) {
+ case 1: return "Express";
+ case 2: return "ESX Server";
+ case 3: return "VMware Server";
Home |
Main Index |
Thread Index |
Old Index