fix build

Signed-off-by: Vasiliy Tolstov <v.tolstov@selfip.ru>
This commit is contained in:
2015-11-09 09:08:44 +00:00
parent d407b82968
commit 414957d985
55 changed files with 35 additions and 77 deletions

272
vendor/github.com/sigma/vmw-guestinfo/bridge/backdoor.c generated vendored Normal file
View File

@@ -0,0 +1,272 @@
/*********************************************************
* Copyright (C) 1999-2015 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation version 2.1 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*********************************************************/
/*********************************************************
* The contents of this file are subject to the terms of the Common
* Development and Distribution License (the "License") version 1.0
* and no later version. You may not use this file except in
* compliance with the License.
*
* You can obtain a copy of the License at
* http://www.opensource.org/licenses/cddl1.php
*
* See the License for the specific language governing permissions
* and limitations under the License.
*
*********************************************************/
/*
* backdoor.c --
*
* First layer of the internal communication channel between guest
* applications and vmware
*
* This is the backdoor. By using special ports of the virtual I/O space,
* and the virtual CPU registers, a guest application can send a
* synchroneous basic request to vmware, and vmware can reply to it.
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "backdoor_def.h"
#include "backdoor.h"
#include "backdoorInt.h"
#if defined(BACKDOOR_DEBUG) && defined(USERLEVEL)
#if defined(__KERNEL__) || defined(_KERNEL)
#else
# include "debug.h"
#endif
# include <stdio.h>
# define BACKDOOR_LOG(args) Debug args
# define BACKDOOR_LOG_PROTO_STRUCT(x) BackdoorPrintProtoStruct((x))
# define BACKDOOR_LOG_HB_PROTO_STRUCT(x) BackdoorPrintHbProtoStruct((x))
/*
*----------------------------------------------------------------------------
*
* BackdoorPrintProtoStruct --
* BackdoorPrintHbProtoStruct --
*
* Print the contents of the specified backdoor protocol structure via
* printf.
*
* Results:
* None.
*
* Side effects:
* Output to stdout.
*
*----------------------------------------------------------------------------
*/
void
BackdoorPrintProtoStruct(Backdoor_proto *myBp)
{
Debug("magic 0x%08x, command %d, size %"FMTSZ"u, port %d\n",
myBp->in.ax.word, myBp->in.cx.halfs.low,
myBp->in.size, myBp->in.dx.halfs.low);
#ifndef VM_X86_64
Debug("ax %#x, "
"bx %#x, "
"cx %#x, "
"dx %#x, "
"si %#x, "
"di %#x\n",
myBp->out.ax.word,
myBp->out.bx.word,
myBp->out.cx.word,
myBp->out.dx.word,
myBp->out.si.word,
myBp->out.di.word);
#else
Debug("ax %#"FMT64"x, "
"bx %#"FMT64"x, "
"cx %#"FMT64"x, "
"dx %#"FMT64"x, "
"si %#"FMT64"x, "
"di %#"FMT64"x\n",
myBp->out.ax.quad,
myBp->out.bx.quad,
myBp->out.cx.quad,
myBp->out.dx.quad,
myBp->out.si.quad,
myBp->out.di.quad);
#endif
}
void
BackdoorPrintHbProtoStruct(Backdoor_proto_hb *myBp)
{
Debug("magic 0x%08x, command %d, size %"FMTSZ"u, port %d, "
"srcAddr %"FMTSZ"u, dstAddr %"FMTSZ"u\n",
myBp->in.ax.word, myBp->in.bx.halfs.low, myBp->in.size,
myBp->in.dx.halfs.low, myBp->in.srcAddr, myBp->in.dstAddr);
#ifndef VM_X86_64
Debug("ax %#x, "
"bx %#x, "
"cx %#x, "
"dx %#x, "
"si %#x, "
"di %#x, "
"bp %#x\n",
myBp->out.ax.word,
myBp->out.bx.word,
myBp->out.cx.word,
myBp->out.dx.word,
myBp->out.si.word,
myBp->out.di.word,
myBp->out.bp.word);
#else
Debug("ax %#"FMT64"x, "
"bx %#"FMT64"x, "
"cx %#"FMT64"x, "
"dx %#"FMT64"x, "
"si %#"FMT64"x, "
"di %#"FMT64"x, "
"bp %#"FMT64"x\n",
myBp->out.ax.quad,
myBp->out.bx.quad,
myBp->out.cx.quad,
myBp->out.dx.quad,
myBp->out.si.quad,
myBp->out.di.quad,
myBp->out.bp.quad);
#endif
}
#else
# define BACKDOOR_LOG(args)
# define BACKDOOR_LOG_PROTO_STRUCT(x)
# define BACKDOOR_LOG_HB_PROTO_STRUCT(x)
#endif
/*
*-----------------------------------------------------------------------------
*
* Backdoor --
*
* Send a low-bandwidth basic request (16 bytes) to vmware, and return its
* reply (24 bytes).
*
* Result:
* None
*
* Side-effects:
* None
*
*-----------------------------------------------------------------------------
*/
void
Backdoor(Backdoor_proto *myBp) // IN/OUT
{
ASSERT(myBp);
myBp->in.ax.word = BDOOR_MAGIC;
myBp->in.dx.halfs.low = BDOOR_PORT;
BACKDOOR_LOG(("Backdoor: before "));
BACKDOOR_LOG_PROTO_STRUCT(myBp);
Backdoor_InOut(myBp);
BACKDOOR_LOG(("Backdoor: after "));
BACKDOOR_LOG_PROTO_STRUCT(myBp);
}
/*
*-----------------------------------------------------------------------------
*
* Backdoor_HbOut --
*
* Send a high-bandwidth basic request to vmware, and return its
* reply.
*
* Result:
* The host-side response is returned via the IN/OUT parameter.
*
* Side-effects:
* Pokes the high-bandwidth backdoor.
*
*-----------------------------------------------------------------------------
*/
void
Backdoor_HbOut(Backdoor_proto_hb *myBp) // IN/OUT
{
ASSERT(myBp);
myBp->in.ax.word = BDOOR_MAGIC;
myBp->in.dx.halfs.low = BDOORHB_PORT;
BACKDOOR_LOG(("Backdoor_HbOut: before "));
BACKDOOR_LOG_HB_PROTO_STRUCT(myBp);
BackdoorHbOut(myBp);
BACKDOOR_LOG(("Backdoor_HbOut: after "));
BACKDOOR_LOG_HB_PROTO_STRUCT(myBp);
}
/*
*-----------------------------------------------------------------------------
*
* Backdoor_HbIn --
*
* Send a basic request to vmware, and return its high-bandwidth
* reply
*
* Result:
* Host-side response returned via the IN/OUT parameter.
*
* Side-effects:
* Pokes the high-bandwidth backdoor.
*
*-----------------------------------------------------------------------------
*/
void
Backdoor_HbIn(Backdoor_proto_hb *myBp) // IN/OUT
{
ASSERT(myBp);
myBp->in.ax.word = BDOOR_MAGIC;
myBp->in.dx.halfs.low = BDOORHB_PORT;
BACKDOOR_LOG(("Backdoor_HbIn: before "));
BACKDOOR_LOG_HB_PROTO_STRUCT(myBp);
BackdoorHbIn(myBp);
BACKDOOR_LOG(("Backdoor_HbIn: after "));
BACKDOOR_LOG_HB_PROTO_STRUCT(myBp);
}
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,235 @@
/*********************************************************
* Copyright (C) 2005-2015 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation version 2.1 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*********************************************************/
/*********************************************************
* The contents of this file are subject to the terms of the Common
* Development and Distribution License (the "License") version 1.0
* and no later version. You may not use this file except in
* compliance with the License.
*
* You can obtain a copy of the License at
* http://www.opensource.org/licenses/cddl1.php
*
* See the License for the specific language governing permissions
* and limitations under the License.
*
*********************************************************/
/*
* backdoorGcc32.c --
*
* Implements the real work for guest-side backdoor for GCC, 32-bit
* target (supports inline ASM, GAS syntax). The asm sections are marked
* volatile since vmware can change the registers content without the
* compiler knowing it.
*
* XXX
* I tried to write this more cleanly, but:
* - There is no way to specify an "ebp" constraint
* - "ebp" is ignored when specified as cloberred register
* - gas barfs when there is more than 10 operands
* - gas 2.7.2.3, depending on the order of the operands, can
* mis-assemble without any warning
* --hpreg
*
* Note that the problems with gas noted above might longer be relevant
* now that we've upgraded most of our compiler versions.
* --rrdharan
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "backdoor.h"
#include "backdoorInt.h"
/*
*----------------------------------------------------------------------------
*
* Backdoor_InOut --
*
* Send a low-bandwidth basic request (16 bytes) to vmware, and return its
* reply (24 bytes).
*
* Results:
* Host-side response returned in bp IN/OUT parameter.
*
* Side effects:
* Pokes the backdoor.
*
*----------------------------------------------------------------------------
*/
void
Backdoor_InOut(Backdoor_proto *myBp) // IN/OUT
{
uint32 dummy;
__asm__ __volatile__(
#ifdef __PIC__
"pushl %%ebx" "\n\t"
#endif
"pushl %%eax" "\n\t"
"movl 20(%%eax), %%edi" "\n\t"
"movl 16(%%eax), %%esi" "\n\t"
"movl 12(%%eax), %%edx" "\n\t"
"movl 8(%%eax), %%ecx" "\n\t"
"movl 4(%%eax), %%ebx" "\n\t"
"movl (%%eax), %%eax" "\n\t"
"inl %%dx, %%eax" "\n\t"
"xchgl %%eax, (%%esp)" "\n\t"
"movl %%edi, 20(%%eax)" "\n\t"
"movl %%esi, 16(%%eax)" "\n\t"
"movl %%edx, 12(%%eax)" "\n\t"
"movl %%ecx, 8(%%eax)" "\n\t"
"movl %%ebx, 4(%%eax)" "\n\t"
"popl (%%eax)" "\n\t"
#ifdef __PIC__
"popl %%ebx" "\n\t"
#endif
: "=a" (dummy)
: "0" (myBp)
/*
* vmware can modify the whole VM state without the compiler knowing
* it. So far it does not modify EFLAGS. --hpreg
*/
:
#ifndef __PIC__
"ebx",
#endif
"ecx", "edx", "esi", "edi", "memory"
);
}
/*
*-----------------------------------------------------------------------------
*
* BackdoorHbIn --
* BackdoorHbOut --
*
* Send a high-bandwidth basic request to vmware, and return its
* reply.
*
* Results:
* Host-side response returned in bp IN/OUT parameter.
*
* Side-effects:
* Pokes the high-bandwidth backdoor port.
*
*-----------------------------------------------------------------------------
*/
void
BackdoorHbIn(Backdoor_proto_hb *myBp) // IN/OUT
{
uint32 dummy;
__asm__ __volatile__(
#ifdef __PIC__
"pushl %%ebx" "\n\t"
#endif
"pushl %%ebp" "\n\t"
"pushl %%eax" "\n\t"
"movl 24(%%eax), %%ebp" "\n\t"
"movl 20(%%eax), %%edi" "\n\t"
"movl 16(%%eax), %%esi" "\n\t"
"movl 12(%%eax), %%edx" "\n\t"
"movl 8(%%eax), %%ecx" "\n\t"
"movl 4(%%eax), %%ebx" "\n\t"
"movl (%%eax), %%eax" "\n\t"
"cld" "\n\t"
"rep; insb" "\n\t"
"xchgl %%eax, (%%esp)" "\n\t"
"movl %%ebp, 24(%%eax)" "\n\t"
"movl %%edi, 20(%%eax)" "\n\t"
"movl %%esi, 16(%%eax)" "\n\t"
"movl %%edx, 12(%%eax)" "\n\t"
"movl %%ecx, 8(%%eax)" "\n\t"
"movl %%ebx, 4(%%eax)" "\n\t"
"popl (%%eax)" "\n\t"
"popl %%ebp" "\n\t"
#ifdef __PIC__
"popl %%ebx" "\n\t"
#endif
: "=a" (dummy)
: "0" (myBp)
/*
* vmware can modify the whole VM state without the compiler knowing
* it. --hpreg
*/
:
#ifndef __PIC__
"ebx",
#endif
"ecx", "edx", "esi", "edi", "memory", "cc"
);
}
void
BackdoorHbOut(Backdoor_proto_hb *myBp) // IN/OUT
{
uint32 dummy;
__asm__ __volatile__(
#ifdef __PIC__
"pushl %%ebx" "\n\t"
#endif
"pushl %%ebp" "\n\t"
"pushl %%eax" "\n\t"
"movl 24(%%eax), %%ebp" "\n\t"
"movl 20(%%eax), %%edi" "\n\t"
"movl 16(%%eax), %%esi" "\n\t"
"movl 12(%%eax), %%edx" "\n\t"
"movl 8(%%eax), %%ecx" "\n\t"
"movl 4(%%eax), %%ebx" "\n\t"
"movl (%%eax), %%eax" "\n\t"
"cld" "\n\t"
"rep; outsb" "\n\t"
"xchgl %%eax, (%%esp)" "\n\t"
"movl %%ebp, 24(%%eax)" "\n\t"
"movl %%edi, 20(%%eax)" "\n\t"
"movl %%esi, 16(%%eax)" "\n\t"
"movl %%edx, 12(%%eax)" "\n\t"
"movl %%ecx, 8(%%eax)" "\n\t"
"movl %%ebx, 4(%%eax)" "\n\t"
"popl (%%eax)" "\n\t"
"popl %%ebp" "\n\t"
#ifdef __PIC__
"popl %%ebx" "\n\t"
#endif
: "=a" (dummy)
: "0" (myBp)
:
#ifndef __PIC__
"ebx",
#endif
"ecx", "edx", "esi", "edi", "memory", "cc"
);
}
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,243 @@
/*********************************************************
* Copyright (C) 2005-2015 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation version 2.1 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*********************************************************/
/*********************************************************
* The contents of this file are subject to the terms of the Common
* Development and Distribution License (the "License") version 1.0
* and no later version. You may not use this file except in
* compliance with the License.
*
* You can obtain a copy of the License at
* http://www.opensource.org/licenses/cddl1.php
*
* See the License for the specific language governing permissions
* and limitations under the License.
*
*********************************************************/
/*
* backdoorGcc64.c --
*
* Implements the real work for guest-side backdoor for GCC, 64-bit
* target (supports inline ASM, GAS syntax). The asm sections are marked
* volatile since vmware can change the registers content without the
* compiler knowing it.
*
* See backdoorGCC32.c (from which this code was mostly copied) for
* details on why the ASM is written this way. Also note that it might be
* possible to write the asm blocks using the symbolic operand specifiers
* in such a way that the same asm would generate correct code for both
* 32-bit and 64-bit targets, but I'm too lazy to figure it all out.
* --rrdharan
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "backdoor.h"
#include "backdoorInt.h"
/*
*----------------------------------------------------------------------------
*
* Backdoor_InOut --
*
* Send a low-bandwidth basic request (16 bytes) to vmware, and return its
* reply (24 bytes).
*
* Results:
* Host-side response returned in bp IN/OUT parameter.
*
* Side effects:
* Pokes the backdoor.
*
*----------------------------------------------------------------------------
*/
void
Backdoor_InOut(Backdoor_proto *myBp) // IN/OUT
{
uint64 dummy;
__asm__ __volatile__(
#ifdef __APPLE__
/*
* Save %rbx on the stack because the Mac OS GCC doesn't want us to
* clobber it - it erroneously thinks %rbx is the PIC register.
* (Radar bug 7304232)
*/
"pushq %%rbx" "\n\t"
#endif
"pushq %%rax" "\n\t"
"movq 40(%%rax), %%rdi" "\n\t"
"movq 32(%%rax), %%rsi" "\n\t"
"movq 24(%%rax), %%rdx" "\n\t"
"movq 16(%%rax), %%rcx" "\n\t"
"movq 8(%%rax), %%rbx" "\n\t"
"movq (%%rax), %%rax" "\n\t"
"inl %%dx, %%eax" "\n\t" /* NB: There is no inq instruction */
"xchgq %%rax, (%%rsp)" "\n\t"
"movq %%rdi, 40(%%rax)" "\n\t"
"movq %%rsi, 32(%%rax)" "\n\t"
"movq %%rdx, 24(%%rax)" "\n\t"
"movq %%rcx, 16(%%rax)" "\n\t"
"movq %%rbx, 8(%%rax)" "\n\t"
"popq (%%rax)" "\n\t"
#ifdef __APPLE__
"popq %%rbx" "\n\t"
#endif
: "=a" (dummy)
: "0" (myBp)
/*
* vmware can modify the whole VM state without the compiler knowing
* it. So far it does not modify EFLAGS. --hpreg
*/
:
#ifndef __APPLE__
/* %rbx is unchanged at the end of the function on Mac OS. */
"rbx",
#endif
"rcx", "rdx", "rsi", "rdi", "memory"
);
}
/*
*-----------------------------------------------------------------------------
*
* BackdoorHbIn --
* BackdoorHbOut --
*
* Send a high-bandwidth basic request to vmware, and return its
* reply.
*
* Results:
* Host-side response returned in bp IN/OUT parameter.
*
* Side-effects:
* Pokes the high-bandwidth backdoor port.
*
*-----------------------------------------------------------------------------
*/
void
BackdoorHbIn(Backdoor_proto_hb *myBp) // IN/OUT
{
uint64 dummy;
__asm__ __volatile__(
"pushq %%rbp" "\n\t"
#ifdef __APPLE__
/*
* Save %rbx on the stack because the Mac OS GCC doesn't want us to
* clobber it - it erroneously thinks %rbx is the PIC register.
* (Radar bug 7304232)
*/
"pushq %%rbx" "\n\t"
#endif
"pushq %%rax" "\n\t"
"movq 48(%%rax), %%rbp" "\n\t"
"movq 40(%%rax), %%rdi" "\n\t"
"movq 32(%%rax), %%rsi" "\n\t"
"movq 24(%%rax), %%rdx" "\n\t"
"movq 16(%%rax), %%rcx" "\n\t"
"movq 8(%%rax), %%rbx" "\n\t"
"movq (%%rax), %%rax" "\n\t"
"cld" "\n\t"
"rep; insb" "\n\t"
"xchgq %%rax, (%%rsp)" "\n\t"
"movq %%rbp, 48(%%rax)" "\n\t"
"movq %%rdi, 40(%%rax)" "\n\t"
"movq %%rsi, 32(%%rax)" "\n\t"
"movq %%rdx, 24(%%rax)" "\n\t"
"movq %%rcx, 16(%%rax)" "\n\t"
"movq %%rbx, 8(%%rax)" "\n\t"
"popq (%%rax)" "\n\t"
#ifdef __APPLE__
"popq %%rbx" "\n\t"
#endif
"popq %%rbp"
: "=a" (dummy)
: "0" (myBp)
/*
* vmware can modify the whole VM state without the compiler knowing
* it. --hpreg
*/
:
#ifndef __APPLE__
/* %rbx is unchanged at the end of the function on Mac OS. */
"rbx",
#endif
"rcx", "rdx", "rsi", "rdi", "memory", "cc"
);
}
void
BackdoorHbOut(Backdoor_proto_hb *myBp) // IN/OUT
{
uint64 dummy;
__asm__ __volatile__(
"pushq %%rbp" "\n\t"
#ifdef __APPLE__
/*
* Save %rbx on the stack because the Mac OS GCC doesn't want us to
* clobber it - it erroneously thinks %rbx is the PIC register.
* (Radar bug 7304232)
*/
"pushq %%rbx" "\n\t"
#endif
"pushq %%rax" "\n\t"
"movq 48(%%rax), %%rbp" "\n\t"
"movq 40(%%rax), %%rdi" "\n\t"
"movq 32(%%rax), %%rsi" "\n\t"
"movq 24(%%rax), %%rdx" "\n\t"
"movq 16(%%rax), %%rcx" "\n\t"
"movq 8(%%rax), %%rbx" "\n\t"
"movq (%%rax), %%rax" "\n\t"
"cld" "\n\t"
"rep; outsb" "\n\t"
"xchgq %%rax, (%%rsp)" "\n\t"
"movq %%rbp, 48(%%rax)" "\n\t"
"movq %%rdi, 40(%%rax)" "\n\t"
"movq %%rsi, 32(%%rax)" "\n\t"
"movq %%rdx, 24(%%rax)" "\n\t"
"movq %%rcx, 16(%%rax)" "\n\t"
"movq %%rbx, 8(%%rax)" "\n\t"
"popq (%%rax)" "\n\t"
#ifdef __APPLE__
"popq %%rbx" "\n\t"
#endif
"popq %%rbp"
: "=a" (dummy)
: "0" (myBp)
:
#ifndef __APPLE__
/* %rbx is unchanged at the end of the function on Mac OS. */
"rbx",
#endif
"rcx", "rdx", "rsi", "rdi", "memory", "cc"
);
}
#ifdef __cplusplus
}
#endif

60
vendor/github.com/sigma/vmw-guestinfo/bridge/bridge.go generated vendored Normal file
View File

@@ -0,0 +1,60 @@
package bridge
/*
#cgo CFLAGS: -I../include
#include <stdlib.h>
#include "message.h"
#include "vmcheck.h"
void Warning(const char *fmt, ...) {}
void Debug(const char *fmt, ...) {}
void Panic(const char *fmt, ...) {}
void Log(const char *fmt, ...) {}
*/
import "C"
import "unsafe"
// MessageChannel provides a channel to pass information from/to the hypervisor
type MessageChannel *C.struct_Message_Channel
// MessageOpen creates a new MessageChannel
func MessageOpen(proto uint32) MessageChannel {
return C.Message_Open(C.uint32(proto))
}
// MessageClose closes a MessageChannel
func MessageClose(c MessageChannel) bool {
status := C.Message_Close(c)
return status != 0
}
// MessageSend sends a request through a MessageChannel
func MessageSend(c MessageChannel, request []byte) bool {
buffer := (*C.uchar)(unsafe.Pointer(&request[0]))
status := C.Message_Send(c, buffer, (C.size_t)(C.int(len(request))))
return status != 0
}
// MessageReceive receives a response through a MessageChannel
func MessageReceive(c MessageChannel) ([]byte, bool) {
var reply *C.uchar
var replyLen C.size_t
defer C.free(unsafe.Pointer(reply))
status := C.Message_Receive(c, &reply, &replyLen)
res := C.GoBytes(unsafe.Pointer(reply), (C.int)(replyLen))
return res, status != 0
}
// VMCheckIsVirtualWorld checks if current code is running in a VMware virtual machine
func VMCheckIsVirtualWorld() bool {
return C.VmCheck_IsVirtualWorld() != 0
}
// VMCheckGetVersion returns the identifiers of the current hypervisor
func VMCheckGetVersion() (uint32, uint32) {
var version C.uint32
var typ C.uint32
C.VmCheck_GetVersion(&version, &typ)
return uint32(version), uint32(typ)
}

439
vendor/github.com/sigma/vmw-guestinfo/bridge/dynbuf.c generated vendored Normal file
View File

@@ -0,0 +1,439 @@
/*********************************************************
* Copyright (C) 1998-2015 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation version 2.1 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*********************************************************/
/*
* dynbuf.c --
*
* Dynamic buffers --hpreg
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "vmware.h"
#include "dynbuf.h"
/*
*-----------------------------------------------------------------------------
*
* DynBuf_Init --
*
* Dynamic buffer constructor --hpreg
*
* Results:
* None
*
* Side effects:
* None
*
*-----------------------------------------------------------------------------
*/
void
DynBuf_Init(DynBuf *b) // OUT:
{
ASSERT(b);
b->data = NULL;
b->size = 0;
b->allocated = 0;
}
/*
*-----------------------------------------------------------------------------
*
* DynBuf_Destroy --
*
* Dynamic buffer destructor --hpreg
*
* Results:
* None
*
* Side effects:
* None
*
*-----------------------------------------------------------------------------
*/
void
DynBuf_Destroy(DynBuf *b) // IN/OUT:
{
ASSERT(b);
free(b->data);
DynBuf_Init(b);
}
/*
*-----------------------------------------------------------------------------
*
* DynBuf_AllocGet --
*
* Retrieve a pointer to the data contained in a dynamic buffer. Return
* a copy of that data.
*
* Results:
* The pointer to the data. NULL on out of memory failure.
*
* Side effects:
* Allocates memory.
*
*-----------------------------------------------------------------------------
*/
void *
DynBuf_AllocGet(DynBuf const *b) // IN
{
void *new_data;
ASSERT(b);
new_data = malloc(b->size);
if (new_data) {
memcpy(new_data, b->data, b->size);
}
return new_data;
}
/*
*-----------------------------------------------------------------------------
*
* DynBuf_Attach --
*
* Grants ownership of the specified buffer to the DynBuf
* object. If there is an existing buffer, it is freed.
*
* Results:
* None.
*
* Side effects:
* None
*
*-----------------------------------------------------------------------------
*/
void
DynBuf_Attach(DynBuf *b, // IN
size_t size, // IN
void *data) // IN
{
ASSERT(b);
ASSERT((size == 0) == (data == NULL));
free(b->data);
b->data = data;
b->size = b->allocated = size;
}
/*
*-----------------------------------------------------------------------------
*
* DynBuf_Detach --
*
* Releases ownership of the buffer stored in the DynBuf object,
* and returns a pointer to it.
*
* Results:
* The pointer to the data.
*
* Side effects:
* None
*
*-----------------------------------------------------------------------------
*/
void *
DynBuf_Detach(DynBuf *b) // IN
{
void *data;
ASSERT(b);
data = b->data;
b->data = NULL;
b->allocated = 0;
return data;
}
/*
*-----------------------------------------------------------------------------
*
* DynBufRealloc --
*
* Reallocate a dynamic buffer --hpreg
*
* Results:
* TRUE on success
* FALSE on failure (not enough memory)
*
* Side effects:
* None
*
*-----------------------------------------------------------------------------
*/
static Bool
DynBufRealloc(DynBuf *b, // IN:
size_t newAllocated) // IN:
{
void *new_data;
ASSERT(b);
new_data = realloc(b->data, newAllocated);
if (new_data == NULL && newAllocated) {
/* Not enough memory */
return FALSE;
}
b->data = new_data;
b->allocated = newAllocated;
return TRUE;
}
/*
*-----------------------------------------------------------------------------
*
* DynBuf_Enlarge --
*
* Enlarge a dynamic buffer. The resulting dynamic buffer is guaranteed to
* be larger than the one you passed, and at least 'minSize' bytes
* large --hpreg
*
* Results:
* TRUE on success
* FALSE on failure (not enough memory)
*
* Side effects:
* None
*
*-----------------------------------------------------------------------------
*/
Bool
DynBuf_Enlarge(DynBuf *b, // IN:
size_t minSize) // IN:
{
size_t newAllocated;
ASSERT(b);
newAllocated = b->allocated
?
#if defined(DYNBUF_DEBUG)
b->allocated + 1
#else
/*
* Double the previously allocated size if it is less
* than 256KB; otherwise grow it linearly by 256KB
*/
(b->allocated < 256 * 1024 ? b->allocated * 2
: b->allocated + 256 * 1024)
#endif
:
#if defined(DYNBUF_DEBUG)
1
#else
/*
* Initial size: 1 KB. Most buffers are smaller than
* that --hpreg
*/
1 << 10
#endif
;
if (minSize > newAllocated) {
newAllocated = minSize;
}
/*
* Prevent integer overflow. We can use this form of checking specifically
* because a multiple by 2 is used (in the worst case). This type of
* checking does not work in the general case.
*/
if (newAllocated < b->allocated) {
return FALSE;
}
return DynBufRealloc(b, newAllocated);
}
/*
*-----------------------------------------------------------------------------
*
* DynBuf_Append --
*
* Append data at the end of a dynamic buffer. 'size' is the size of the
* data. If it is <= 0, no operation is performed --hpreg
*
* Results:
* TRUE on success
* FALSE on failure (not enough memory)
*
* Side effects:
* None
*
*-----------------------------------------------------------------------------
*/
Bool
DynBuf_Append(DynBuf *b, // IN
void const *data, // IN
size_t size) // IN
{
size_t new_size;
ASSERT(b);
if (size <= 0) {
return TRUE;
}
ASSERT(data);
new_size = b->size + size;
if (new_size < b->size) { // Prevent integer overflow
return FALSE;
}
if (new_size > b->allocated) {
/* Not enough room */
if (DynBuf_Enlarge(b, new_size) == FALSE) {
return FALSE;
}
}
memcpy(b->data + b->size, data, size);
b->size = new_size;
return TRUE;
}
/*
*-----------------------------------------------------------------------------
*
* DynBuf_SafeInternalAppend --
*
* Append data at the end of a dynamic buffer. Memory allocation failure
* are handled the same way as Util_SafeMalloc, that is to say, with a
* Panic.
*
* Results:
* None
*
* Side effects:
* None
*
*-----------------------------------------------------------------------------
*/
void
DynBuf_SafeInternalAppend(DynBuf *b, // IN
void const *data, // IN
size_t size, // IN
char const *file, // IN
unsigned int lineno) // IN
{
if (!DynBuf_Append(b, data, size)) {
Panic("Unrecoverable memory allocation failure at %s:%u\n",
file, lineno);
}
}
/*
*-----------------------------------------------------------------------------
*
* DynBuf_Trim --
*
* Reallocate a dynamic buffer to the exact size it occupies --hpreg
*
* Results:
* TRUE on success
* FALSE on failure (not enough memory)
*
* Side effects:
* None
*
*-----------------------------------------------------------------------------
*/
Bool
DynBuf_Trim(DynBuf *b) // IN
{
ASSERT(b);
return DynBufRealloc(b, b->size);
}
/*
*-----------------------------------------------------------------------------
*
* DynBuf_Copy --
*
* Copies all data and metadata from src dynbuff to dest dynbuf.
*
* Dest should be an initialized DynBuf of alloced length zero
* to prevent memory leaks.
*
* Results:
* TRUE on success, FALSE on failure.
*
* Side effects:
* None
*
*-----------------------------------------------------------------------------
*/
Bool
DynBuf_Copy(DynBuf *src, // IN
DynBuf *dest) // OUT
{
ASSERT(src);
ASSERT(dest);
ASSERT(!dest->data);
dest->data = malloc(src->allocated);
if (dest->data == NULL) {
return FALSE;
}
dest->size = src->size;
dest->allocated = src->allocated;
memcpy(dest->data, src->data, src->size);
return TRUE;
}

336
vendor/github.com/sigma/vmw-guestinfo/bridge/hostinfo.c generated vendored Normal file
View File

@@ -0,0 +1,336 @@
/*********************************************************
* Copyright (C) 1998-2015 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation version 2.1 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*********************************************************/
/*
* hostinfo.c --
*
* Platform-independent code that calls into hostinfo<OS>-specific
* code.
*/
#include "vmware.h"
#include <string.h>
#if defined(__i386__) || defined(__x86_64__)
#include "cpuid_info.h"
#endif
#include "hostinfo.h"
#include "hostinfoInt.h"
#include "util.h"
/* #include "str.h" */
#include <stdio.h>
#define Str_Sprintf snprintf
#include "dynbuf.h"
#include "backdoor_def.h"
/*
* #define LOGLEVEL_MODULE hostinfo
* #include "loglevel_user.h"
*/
#define LGPFX "HOSTINFO:"
/*
* HostinfoOSData caches its returned value.
*/
volatile Bool HostinfoOSNameCacheValid = FALSE;
char HostinfoCachedOSName[MAX_OS_NAME_LEN];
char HostinfoCachedOSFullName[MAX_OS_FULLNAME_LEN];
#if defined(__i386__) || defined(__x86_64__)
/*
*-----------------------------------------------------------------------------
*
* HostInfoGetCpuidStrSection --
*
* Append a section (either low or high) of CPUID as a string in DynBuf.
* E.g.
* 00000000:00000005756E65476C65746E49656E69-
* 00000001:00000F4A000208000000649DBFEBFBFF-
* or
* 80000000:80000008000000000000000000000000-
* 80000001:00000000000000000000000120100000-
* 80000008:00003024000000000000000000000000-
*
* The returned eax of args[0] is used to determine the upper bound for
* the following input arguments. And the input args should be in
* ascending order.
*
* Results:
* None. The string will be appended in buf.
*
* Side effect:
* None
*
*-----------------------------------------------------------------------------
*/
static void
HostInfoGetCpuidStrSection(const uint32 args[], // IN: input eax arguments
const size_t args_size, // IN: size of the argument array
DynBuf *buf) // IN/OUT: result string in DynBuf
{
static const char format[] = "%08X:%08X%08X%08X%08X-";
CPUIDRegs reg;
uint32 max_arg;
char temp[64];
int i;
__GET_CPUID(args[0], &reg);
max_arg = reg.eax;
if (max_arg < args[0]) {
Warning(LGPFX" No CPUID information available. Based = %08X.\n",
args[0]);
return;
}
DynBuf_Append(buf, temp,
Str_Sprintf(temp, sizeof temp, format, args[0], reg.eax,
reg.ebx, reg.ecx, reg.edx));
for (i = 1; i < args_size && args[i] <= max_arg; i++) {
ASSERT(args[i] > args[i - 1]); // Ascending order.
__GET_CPUID(args[i], &reg);
DynBuf_Append(buf, temp,
Str_Sprintf(temp, sizeof temp, format, args[i], reg.eax,
reg.ebx, reg.ecx, reg.edx));
}
}
/*
*-----------------------------------------------------------------------------
*
* Hostinfo_GetCpuidStr --
*
* Get the basic and extended CPUID as a string. E.g.
* 00000000:00000005756E65476C65746E49656E69-
* 00000001:00000F4A000208000000649DBFEBFBFF-
* 80000000:80000008000000000000000000000000-
* 80000001:00000000000000000000000120100000-
* 80000008:00003024000000000000000000000000
*
* If the extended CPUID is not available, only returns the basic CPUID.
*
* Results:
* The CPUID string if the processor supports the CPUID instruction and
* this is a processor we recognize. It should never fail, since it
* would at least return leaf 0. Caller needs to free the returned string.
*
* Side effect:
* None
*
*-----------------------------------------------------------------------------
*/
char *
Hostinfo_GetCpuidStr(void)
{
static const uint32 basic_args[] = {0x0, 0x1, 0xa};
static const uint32 extended_args[] = {0x80000000, 0x80000001, 0x80000008};
DynBuf buf;
char *result;
DynBuf_Init(&buf);
HostInfoGetCpuidStrSection(basic_args, ARRAYSIZE(basic_args), &buf);
HostInfoGetCpuidStrSection(extended_args, ARRAYSIZE(extended_args), &buf);
// Trim buffer and set NULL character to replace last '-'.
DynBuf_Trim(&buf);
result = (char*)DynBuf_Get(&buf);
ASSERT(result && result[0]); // We should at least get result from eax = 0x0.
result[DynBuf_GetSize(&buf) - 1] = '\0';
return DynBuf_Detach(&buf);
}
#endif // defined(__i386__) || defined(__x86_64__)
/*
*-----------------------------------------------------------------------------
*
* Hostinfo_GetCpuid --
*
* Get cpuid information for a CPU. Which CPU the information is for
* depends on the OS scheduler. We are assuming that all CPUs in
* the system have identical numbers of cores and threads.
*
* Results:
* TRUE if the processor supports the cpuid instruction and this
* is a process we recognize, FALSE otherwise.
*
* Side effect:
* None
*
*-----------------------------------------------------------------------------
*/
Bool
Hostinfo_GetCpuid(HostinfoCpuIdInfo *info) // OUT
{
#if defined(__i386__) || defined(__x86_64__)
CPUIDSummary cpuid;
CPUIDRegs id0;
/*
* Can't do cpuid = {0} as an initializer above because gcc throws
* some idiotic warning.
*/
memset(&cpuid, 0, sizeof(cpuid));
/*
* Get basic and extended CPUID info.
*/
__GET_CPUID(0, &id0);
cpuid.id0.numEntries = id0.eax;
if (0 == cpuid.id0.numEntries) {
Warning(LGPFX" No CPUID information available.\n");
return FALSE;
}
*(uint32*)(cpuid.id0.name + 0) = id0.ebx;
*(uint32*)(cpuid.id0.name + 4) = id0.edx;
*(uint32*)(cpuid.id0.name + 8) = id0.ecx;
*(uint32*)(cpuid.id0.name + 12) = 0;
__GET_CPUID(1, (CPUIDRegs*)&cpuid.id1);
__GET_CPUID(0xa, (CPUIDRegs*)&cpuid.ida);
__GET_CPUID(0x80000000, (CPUIDRegs*)&cpuid.id80);
__GET_CPUID(0x80000001, (CPUIDRegs*)&cpuid.id81);
__GET_CPUID(0x80000008, (CPUIDRegs*)&cpuid.id88);
/*
* Calculate vendor information.
*/
if (0 == strcmp(cpuid.id0.name, CPUID_INTEL_VENDOR_STRING_FIXED)) {
info->vendor = CPUID_VENDOR_INTEL;
} else if (strcmp(cpuid.id0.name, CPUID_AMD_VENDOR_STRING_FIXED) == 0) {
info->vendor = CPUID_VENDOR_AMD;
} else {
info->vendor = CPUID_VENDOR_UNKNOWN;
}
/*
* Pull out versioning and feature information.
*/
info->version = cpuid.id1.version;
info->family = CPUID_GET(1, EAX, FAMILY, cpuid.id1.version);
info->model = CPUID_GET(1, EAX, MODEL, cpuid.id1.version);
info->stepping = CPUID_GET(1, EAX, STEPPING, cpuid.id1.version);
info->type = (cpuid.id1.version >> 12) & 0x0003;
info->extfeatures = cpuid.id1.ecxFeatures;
info->features = cpuid.id1.edxFeatures;
return TRUE;
#else // defined(__i386__) || defined(__x86_64__)
return FALSE;
#endif // defined(__i386__) || defined(__x86_64__)
}
/*
*-----------------------------------------------------------------------------
*
* Hostinfo_GetOSName --
*
* Query the operating system and build a string to identify it.
*
* Examples:
* Windows: <OS NAME> <SERVICE PACK> (Build <BUILD_NUMBER>)
* example: Windows XP Professional Service Pack 2 (Build 2600)
*
* Linux: <OS NAME> <OS RELEASE> <SPECIFIC_DISTRO_INFO>
* example: Linux 2.4.18-3 Red Hat Linux release 7.3 (Valhalla)
*
* Mac OS: <OS NAME> <OS VERSION> (<BUILD VERSION>) <KERNEL NAME> <KERNEL RELEASE>
* example: Mac OS X 10.8.5 (12F45) Darwin 12.5.0
*
* Return value:
* NULL Unable to obtain the OS name.
* !NULL The OS name. The caller is responsible for freeing it.
*
* Side effects:
* Memory is allocated.
*
*-----------------------------------------------------------------------------
*/
/*
* char *
* Hostinfo_GetOSName(void)
* {
* char *name;
* Bool data = HostinfoOSNameCacheValid ? TRUE : HostinfoOSData();
*
* if (data) {
* name = Util_SafeStrdup(HostinfoCachedOSFullName);
* } else {
* name = NULL;
* }
*
* return name;
* }
*/
/*
*-----------------------------------------------------------------------------
*
* Hostinfo_GetOSGuestString --
*
* Query the operating system and build a string to identify it. The
* returned string is the same as you'd see in a VM's .vmx file.
*
* Return value:
* NULL Unable to obtain the OS name.
* !NULL The OS name. The caller is responsible for freeing it.
*
* Side effects:
* Memory is allocated.
*
*-----------------------------------------------------------------------------
*/
/*
* char *
* Hostinfo_GetOSGuestString(void)
* {
* char *name;
* Bool data = HostinfoOSNameCacheValid ? TRUE : HostinfoOSData();
*
* if (data) {
* name = Util_SafeStrdup(HostinfoCachedOSName);
* } else {
* name = NULL;
* }
*
* return name;
* }
*/

View File

@@ -0,0 +1,686 @@
/*********************************************************
* Copyright (C) 2011-2015 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation version 2.1 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*********************************************************/
/*
* hostinfoHV.c --
*
* Code to detect different hypervisors and features.
*/
#include <string.h>
#include "vmware.h"
#if defined(__i386__) || defined(__x86_64__)
# include "cpuid_info.h"
# include "backdoor_def.h"
# include "backdoor_types.h"
#endif
#include "hostinfo.h"
#include "util.h"
#define LGPFX "HOSTINFO:"
/*
* #define LOGLEVEL_MODULE hostinfo
* #include "loglevel_user.h"
*/
/*
*----------------------------------------------------------------------
*
* Hostinfo_HypervisorCPUIDSig --
*
* Get the hypervisor signature string from CPUID.
*
* Results:
* Unqualified 16 byte nul-terminated hypervisor string
* String may contain garbage and caller must free
*
* Side effects:
* None
*
*----------------------------------------------------------------------
*/
char *
Hostinfo_HypervisorCPUIDSig(void)
{
uint32 *name = NULL;
#if defined(__i386__) || defined(__x86_64__)
CPUIDRegs regs;
__GET_CPUID(1, &regs);
if (!CPUID_ISSET(1, ECX, HYPERVISOR, regs.ecx)) {
return NULL;
}
regs.ebx = 0;
regs.ecx = 0;
regs.edx = 0;
__GET_CPUID(0x40000000, &regs);
if (regs.eax < 0x40000000) {
Log(LGPFX" CPUID hypervisor bit is set, but no "
"hypervisor vendor signature is present\n");
}
name = Util_SafeMalloc(4 * sizeof *name);
name[0] = regs.ebx;
name[1] = regs.ecx;
name[2] = regs.edx;
name[3] = 0;
#endif // defined(__i386__) || defined(__x86_64__)
return (char *)name;
}
/*
*----------------------------------------------------------------------
*
* Hostinfo_TouchXen --
*
* Check for Xen.
*
* Official way is to call Hostinfo_HypervisorCPUIDSig(), which
* returns a hypervisor string. This is a secondary check
* that guards against a backdoor failure. See PR156185,
* http://xenbits.xensource.com/xen-unstable.hg?file/6a383beedf83/tools/misc/xen-detect.c
* (Canonical way is /proc/xen, but CPUID is better).
*
* Results:
* TRUE if we are running in a Xen dom0 or domU.
* Linux:
* Illegal instruction exception on real hardware.
* Obscure Xen implementations might return FALSE.
* Windows:
* FALSE on real hardware.
*
* Side effects:
* Linux: Will raise exception on native hardware.
* Windows: None.
*
*----------------------------------------------------------------------
*/
Bool
Hostinfo_TouchXen(void)
{
#if defined(linux) && (defined(__i386__) || defined(__x86_64__))
#define XEN_CPUID 0x40000000
CPUIDRegs regs;
uint32 name[4];
/*
* PV mode: ud2a "xen" cpuid (faults on native hardware).
* (Only Linux can run PV, so skip others here).
* Since PV cannot trap CPUID, this is a Xen hook.
*/
regs.eax = XEN_CPUID;
__asm__ __volatile__(
"xchgl %%ebx, %0" "\n\t"
"ud2a ; .ascii \"xen\" ; cpuid" "\n\t"
"xchgl %%ebx, %0"
: "=&r" (regs.ebx), "=&c" (regs.ecx), "=&d" (regs.edx)
: "a" (regs.eax)
);
name[0] = regs.ebx;
name[1] = regs.ecx;
name[2] = regs.edx;
name[3] = 0;
if (0 == strcmp(CPUID_XEN_HYPERVISOR_VENDOR_STRING, (const char*)name)) {
return TRUE;
}
/* Passed checks. But native and anything non-Xen would #UD before here. */
NOT_TESTED();
Log("Xen detected but hypervisor unrecognized (Xen variant?)\n");
Log("CPUID 0x4000 0000: eax=%x ebx=%x ecx=%x edx=%x\n",
regs.eax, regs.ebx, regs.ecx, regs.edx);
#endif
return FALSE;
}
/*
*----------------------------------------------------------------------
*
* Hostinfo_SLC64Supported --
*
* Access the backdoor with an SLC64 control query. This is used
* to determine if we are running in a VM that supports SLC64.
* This function should only be called after determining that the
* backdoor is present with Hostinfo_TouchBackdoor().
*
* Results:
* TRUE if the outer VM supports SLC64.
* FALSE otherwise.
*
* Side effects:
* Exception if not in a VM, so don't do that!
*
*----------------------------------------------------------------------
*/
Bool
Hostinfo_SLC64Supported(void)
{
#if defined(__i386__) || defined(__x86_64__)
return Hostinfo_VCPUInfoBackdoor(BDOOR_CMD_VCPU_SLC64);
#else
return FALSE;
#endif
}
/*
*----------------------------------------------------------------------
*
* Hostinfo_NestedHVReplaySupported --
*
* Access the backdoor with a HV replay control query. This is used
* to determine if we are running in a VM that supports nested HV replay.
* This function should only be called after determining that the
* backdoor is present with Hostinfo_TouchBackdoor().
*
* Results:
* TRUE if the outer VM supports nexted HV replay.
* FALSE otherwise.
*
* Side effects:
* Exception if not in a VM, so don't do that!
*
*----------------------------------------------------------------------
*/
Bool
Hostinfo_NestedHVReplaySupported(void)
{
#if defined(__i386__) || defined(__x86_64__)
return Hostinfo_VCPUInfoBackdoor(BDOOR_CMD_VCPU_HV_REPLAY_OK);
#else
return FALSE;
#endif
}
/*
*----------------------------------------------------------------------
*
* Hostinfo_SynchronizedVTSCs --
*
* Access the backdoor to determine if the VCPUs' TSCs are
* synchronized.
*
* Results:
* TRUE if the outer VM provides synchronized VTSCs.
* FALSE otherwise.
*
* Side effects:
* Exception if not in a VM, so don't do that!
*
*----------------------------------------------------------------------
*/
Bool
Hostinfo_SynchronizedVTSCs(void)
{
#if defined(__i386__) || defined(__x86_64__)
return Hostinfo_VCPUInfoBackdoor(BDOOR_CMD_VCPU_SYNC_VTSCS);
#else
return FALSE;
#endif
}
#if defined(_WIN32)
#if defined(_WIN64)
// from touchBackdoorMasm64.asm
void Hostinfo_BackdoorInOut(Backdoor_proto *myBp);
#endif
/*
*----------------------------------------------------------------------
*
* Hostinfo_TouchBackDoor --
*
* Access the backdoor. This is used to determine if we are
* running in a VM or on a physical host. On a physical host
* this should generate a GP which we catch and thereby determine
* that we are not in a VM. However some OSes do not handle the
* GP correctly and the process continues running returning garbage.
* In this case we check the EBX register which should be
* BDOOR_MAGIC if the IN was handled in a VM. Based on this we
* return either TRUE or FALSE.
*
* Results:
* TRUE if we succesfully accessed the backdoor, FALSE or segfault
* if not.
*
* Side effects:
* Exception if not in a VM.
*
*----------------------------------------------------------------------
*/
Bool
Hostinfo_TouchBackDoor(void)
{
uint32 ebxval;
#if defined(_WIN64)
Backdoor_proto bp;
bp.in.ax.quad = BDOOR_MAGIC;
bp.in.size = ~BDOOR_MAGIC;
bp.in.cx.quad = BDOOR_CMD_GETVERSION;
bp.in.dx.quad = BDOOR_PORT;
Hostinfo_BackdoorInOut(&bp);
ebxval = bp.out.bx.words.low;
#else // _WIN64
_asm {
push edx
push ecx
push ebx
mov ecx, BDOOR_CMD_GETVERSION
mov ebx, ~BDOOR_MAGIC
mov eax, BDOOR_MAGIC
mov dx, BDOOR_PORT
in eax, dx
mov ebxval, ebx
pop ebx
pop ecx
pop edx
}
#endif // _WIN64
return (ebxval == BDOOR_MAGIC) ? TRUE : FALSE;
}
/*
*----------------------------------------------------------------------
*
* Hostinfo_TouchVirtualPC --
*
* Access MS Virtual PC's backdoor. This is used to determine if
* we are running in a MS Virtual PC or on a physical host. Works
* the same as Hostinfo_TouchBackDoor, except the entry to MS VPC
* is an invalid opcode instead or writing to a port. Since
* MS VPC is 32-bit only, the WIN64 path returns FALSE.
* See: See: http://www.codeproject.com/KB/system/VmDetect.aspx
*
* Results:
* TRUE if we succesfully accessed MS Virtual PC, FALSE or
* segfault if not.
*
* Side effects:
* Exception if not in a VM.
*
*----------------------------------------------------------------------
*/
Bool
Hostinfo_TouchVirtualPC(void)
{
#if defined(_WIN64)
return FALSE; // MS Virtual PC is 32-bit only
#else // _WIN32
uint32 ebxval;
_asm {
push ebx
mov ebx, 0
mov eax, 1 // Virtual PC function number
// execute invalid opcode to call into MS Virtual PC
__emit 0Fh
__emit 3Fh
__emit 07h
__emit 0Bh
mov ebxval, ebx
pop ebx
}
return !ebxval; // ebx is zero if inside Virtual PC
#endif
}
/*
*----------------------------------------------------------------------
*
* Hostinfo_NestingSupported --
*
* Access the backdoor with a nesting control query. This is used
* to determine if we are running in a VM that supports nesting.
* This function should only be called after determining that the
* backdoor is present with Hostinfo_TouchBackdoor().
*
* Results:
* TRUE if the outer VM supports nesting.
* FALSE otherwise.
*
* Side effects:
* Exception if not in a VM, so don't do that!
*
*----------------------------------------------------------------------
*/
Bool
Hostinfo_NestingSupported(void)
{
uint32 cmd = NESTING_CONTROL_QUERY << 16 | BDOOR_CMD_NESTING_CONTROL;
uint32 result;
#if defined(_WIN64)
Backdoor_proto bp;
bp.in.ax.quad = BDOOR_MAGIC;
bp.in.cx.quad = cmd;
bp.in.dx.quad = BDOOR_PORT;
Hostinfo_BackdoorInOut(&bp);
result = bp.out.ax.words.low;
#else
_asm {
push edx
push ecx
mov ecx, cmd
mov eax, BDOOR_MAGIC
mov dx, BDOOR_PORT
in eax, dx
mov result, eax
pop ecx
pop edx
}
#endif
if (result >= NESTING_CONTROL_QUERY && result != ~0U) {
return TRUE;
}
return FALSE;
}
/*
*----------------------------------------------------------------------
*
* Hostinfo_VCPUInfoBackdoor --
*
* Access the backdoor with an VCPU info query. This is used to
* determine whether a VCPU supports a particular feature,
* determined by 'bit'. This function should only be called after
* determining that the backdoor is present with
* Hostinfo_TouchBackdoor().
*
* Results:
* TRUE if the outer VM supports the feature.
* FALSE otherwise.
*
* Side effects:
* Exception if not in a VM, so don't do that!
*
*----------------------------------------------------------------------
*/
Bool
Hostinfo_VCPUInfoBackdoor(unsigned bit)
{
uint32 cmd = BDOOR_CMD_GET_VCPU_INFO;
uint32 result;
#if defined(_WIN64)
Backdoor_proto bp;
bp.in.ax.quad = BDOOR_MAGIC;
bp.in.cx.quad = cmd;
bp.in.dx.quad = BDOOR_PORT;
Hostinfo_BackdoorInOut(&bp);
result = bp.out.ax.words.low;
#else
_asm {
push edx
push ecx
mov ecx, cmd
mov eax, BDOOR_MAGIC
mov dx, BDOOR_PORT
in eax, dx
mov result, eax
pop ecx
pop edx
}
#endif
/* If reserved bit is 1, this command wasn't implemented. */
return (result & (1 << BDOOR_CMD_VCPU_RESERVED)) == 0 &&
(result & (1 << bit)) != 0;
}
#else
/*
*----------------------------------------------------------------------
*
* Hostinfo_TouchBackDoor --
*
* Access the backdoor. This is used to determine if we are
* running in a VM or on a physical host. On a physical host
* this should generate a GP which we catch and thereby determine
* that we are not in a VM. However some OSes do not handle the
* GP correctly and the process continues running returning garbage.
* In this case we check the EBX register which should be
* BDOOR_MAGIC if the IN was handled in a VM. Based on this we
* return either TRUE or FALSE.
*
* Results:
* TRUE if we succesfully accessed the backdoor, FALSE or segfault
* if not.
*
* Side effects:
* Exception if not in a VM.
*
*----------------------------------------------------------------------
*/
Bool
Hostinfo_TouchBackDoor(void)
{
#if defined(__i386__) || defined(__x86_64__)
uint32 eax;
uint32 ebx;
uint32 ecx;
__asm__ __volatile__(
# if defined __PIC__ && !vm_x86_64 // %ebx is reserved by the compiler.
"xchgl %%ebx, %1" "\n\t"
"inl %%dx, %%eax" "\n\t"
"xchgl %%ebx, %1"
: "=a" (eax),
"=&rm" (ebx),
# else
"inl %%dx, %%eax"
: "=a" (eax),
"=b" (ebx),
# endif
"=c" (ecx)
: "0" (BDOOR_MAGIC),
"1" (~BDOOR_MAGIC),
"2" (BDOOR_CMD_GETVERSION),
"d" (BDOOR_PORT)
);
if (ebx == BDOOR_MAGIC) {
return TRUE;
}
#endif
return FALSE;
}
/*
*----------------------------------------------------------------------
*
* Hostinfo_TouchVirtualPC --
*
* Access MS Virtual PC's backdoor. This is used to determine if
* we are running in a MS Virtual PC or on a physical host. Works
* the same as Hostinfo_TouchBackDoor, except the entry to MS VPC
* is an invalid opcode instead or writing to a port. Since
* MS VPC is 32-bit only, the 64-bit path returns FALSE.
* See: http://www.codeproject.com/KB/system/VmDetect.aspx
*
* Results:
* TRUE if we succesfully accessed MS Virtual PC, FALSE or
* segfault if not.
*
* Side effects:
* Exception if not in a VM.
*
*----------------------------------------------------------------------
*/
Bool
Hostinfo_TouchVirtualPC(void)
{
#if defined vm_x86_64
return FALSE;
#else
uint32 ebxval;
__asm__ __volatile__ (
# if defined __PIC__ // %ebx is reserved by the compiler.
"xchgl %%ebx, %1" "\n\t"
".long 0x0B073F0F" "\n\t"
"xchgl %%ebx, %1"
: "=&rm" (ebxval)
: "a" (1),
"0" (0)
# else
".long 0x0B073F0F"
: "=b" (ebxval)
: "a" (1),
"b" (0)
# endif
);
return !ebxval; // %%ebx is zero if inside Virtual PC
#endif
}
/*
*----------------------------------------------------------------------
*
* Hostinfo_NestingSupported --
*
* Access the backdoor with a nesting control query. This is used
* to determine if we are running inside a VM that supports nesting.
* This function should only be called after determining that the
* backdoor is present with Hostinfo_TouchBackdoor().
*
* Results:
* TRUE if the outer VM supports nesting.
* FALSE otherwise.
*
* Side effects:
* Exception if not in a VM, so don't do that!
*
*----------------------------------------------------------------------
*/
Bool
Hostinfo_NestingSupported(void)
{
#if defined(__i386__) || defined(__x86_64__)
uint32 cmd = NESTING_CONTROL_QUERY << 16 | BDOOR_CMD_NESTING_CONTROL;
uint32 result;
__asm__ __volatile__(
"inl %%dx, %%eax"
: "=a" (result)
: "0" (BDOOR_MAGIC),
"c" (cmd),
"d" (BDOOR_PORT)
);
if (result >= NESTING_CONTROL_QUERY && result != ~0U) {
return TRUE;
}
#endif
return FALSE;
}
/*
*----------------------------------------------------------------------
*
* Hostinfo_VCPUInfoBackdoor --
*
* Access the backdoor with an VCPU info query. This is used to
* determine whether a VCPU supports a particular feature,
* determined by 'bit'. This function should only be called after
* determining that the backdoor is present with
* Hostinfo_TouchBackdoor().
*
* Results:
* TRUE if the outer VM supports the feature.
* FALSE otherwise.
*
* Side effects:
* Exception if not in a VM, so don't do that!
*
*----------------------------------------------------------------------
*/
Bool
Hostinfo_VCPUInfoBackdoor(unsigned bit)
{
#if defined(__i386__) || defined(__x86_64__)
uint32 result;
__asm__ __volatile__(
"inl %%dx, %%eax"
: "=a" (result)
: "0" (BDOOR_MAGIC),
"c" (BDOOR_CMD_GET_VCPU_INFO),
"d" (BDOOR_PORT)
);
/* If reserved bit is 1, this command wasn't implemented. */
return (result & (1 << BDOOR_CMD_VCPU_RESERVED)) == 0 &&
(result & (1 << bit)) != 0;
#endif
return FALSE;
}
#endif

605
vendor/github.com/sigma/vmw-guestinfo/bridge/message.c generated vendored Normal file
View File

@@ -0,0 +1,605 @@
/*********************************************************
* Copyright (C) 1999-2015 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation version 2.1 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*********************************************************/
/*********************************************************
* The contents of this file are subject to the terms of the Common
* Development and Distribution License (the "License") version 1.0
* and no later version. You may not use this file except in
* compliance with the License.
*
* You can obtain a copy of the License at
* http://www.opensource.org/licenses/cddl1.php
*
* See the License for the specific language governing permissions
* and limitations under the License.
*
*********************************************************/
/*
* message.c --
*
* Second layer of the internal communication channel between guest
* applications and vmware
*
* Build a generic messaging system between guest applications and vmware.
*
* The protocol is not completely symmetrical, because:
* . basic requests can only be sent by guest applications (when vmware
* wants to post a message to a guest application, the message will be
* really fetched only when the guest application will poll for new
* available messages)
* . several guest applications can talk to vmware, while the contrary is
* not true
*
* Operations that are not atomic (in terms of number of backdoor calls)
* can be aborted by vmware if a checkpoint/restore occurs in the middle of
* such an operation. This layer takes care of retrying those operations.
*/
#ifdef __cplusplus
extern "C" {
#endif
#if defined(__KERNEL__) || defined(_KERNEL) || defined(KERNEL)
# include "kernelStubs.h"
#else
# include <stdio.h>
# include <stdlib.h>
# include "debug.h"
#endif
#include "backdoor_def.h"
#include "guest_msg_def.h"
#include "backdoor.h"
#include "message.h"
#if defined(MESSAGE_DEBUG)
# define MESSAGE_LOG(...) Warning(__VA_ARGS__)
#else
# define MESSAGE_LOG(...)
#endif
/* The channel object */
struct Message_Channel {
/* Identifier */
uint16 id;
/* Reception buffer */
/* Data */
unsigned char *in;
/* Allocated size */
size_t inAlloc;
/* The cookie */
uint32 cookieHigh;
uint32 cookieLow;
};
/*
*-----------------------------------------------------------------------------
*
* Message_Open --
*
* Open a communication channel
*
* Result:
* An allocated Message_Channel on success
* NULL on failure
*
* Side-effects:
* None
*
*-----------------------------------------------------------------------------
*/
Message_Channel *
Message_Open(uint32 proto) // IN
{
Message_Channel *chan;
uint32 flags;
Backdoor_proto bp;
chan = (Message_Channel *)malloc(sizeof(*chan));
if (chan == NULL) {
goto error_quit;
}
flags = GUESTMSG_FLAG_COOKIE;
retry:
/* IN: Type */
bp.in.cx.halfs.high = MESSAGE_TYPE_OPEN;
/* IN: Magic number of the protocol and flags */
bp.in.size = proto | flags;
bp.in.cx.halfs.low = BDOOR_CMD_MESSAGE;
Backdoor(&bp);
/* OUT: Status */
if ((bp.in.cx.halfs.high & MESSAGE_STATUS_SUCCESS) == 0) {
if (flags) {
/* Cookies not supported. Fall back to no cookie. --hpreg */
flags = 0;
goto retry;
}
MESSAGE_LOG("Message: Unable to open a communication channel\n");
goto error_quit;
}
/* OUT: Id and cookie */
chan->id = bp.in.dx.halfs.high;
chan->cookieHigh = bp.out.si.word;
chan->cookieLow = bp.out.di.word;
/* Initialize the channel */
chan->in = NULL;
chan->inAlloc = 0;
return chan;
error_quit:
free(chan);
chan = NULL;
return NULL;
}
/*
*-----------------------------------------------------------------------------
*
* Message_Send --
*
* Send a message over a communication channel
*
* Result:
* TRUE on success
* FALSE on failure (the message is discarded by vmware)
*
* Side-effects:
* None
*
*-----------------------------------------------------------------------------
*/
Bool
Message_Send(Message_Channel *chan, // IN/OUT
const unsigned char *buf, // IN
size_t bufSize) // IN
{
const unsigned char *myBuf;
size_t myBufSize;
Backdoor_proto bp;
retry:
myBuf = buf;
myBufSize = bufSize;
/*
* Send the size.
*/
/* IN: Type */
bp.in.cx.halfs.high = MESSAGE_TYPE_SENDSIZE;
/* IN: Id and cookie */
bp.in.dx.halfs.high = chan->id;
bp.in.si.word = chan->cookieHigh;
bp.in.di.word = chan->cookieLow;
/* IN: Size */
bp.in.size = myBufSize;
bp.in.cx.halfs.low = BDOOR_CMD_MESSAGE;
Backdoor(&bp);
/* OUT: Status */
if ((bp.in.cx.halfs.high & MESSAGE_STATUS_SUCCESS) == 0) {
MESSAGE_LOG("Message: Unable to send a message over the communication "
"channel %u\n", chan->id);
return FALSE;
}
if (bp.in.cx.halfs.high & MESSAGE_STATUS_HB) {
/*
* High-bandwidth backdoor port supported. Send the message in one
* backdoor operation. --hpreg
*/
if (myBufSize) {
Backdoor_proto_hb bphb;
bphb.in.bx.halfs.low = BDOORHB_CMD_MESSAGE;
bphb.in.bx.halfs.high = MESSAGE_STATUS_SUCCESS;
bphb.in.dx.halfs.high = chan->id;
bphb.in.bp.word = chan->cookieHigh;
bphb.in.dstAddr = chan->cookieLow;
bphb.in.size = myBufSize;
bphb.in.srcAddr = (uintptr_t) myBuf;
Backdoor_HbOut(&bphb);
if ((bphb.in.bx.halfs.high & MESSAGE_STATUS_SUCCESS) == 0) {
if ((bphb.in.bx.halfs.high & MESSAGE_STATUS_CPT) != 0) {
/* A checkpoint occurred. Retry the operation. --hpreg */
goto retry;
}
MESSAGE_LOG("Message: Unable to send a message over the "
"communication channel %u\n", chan->id);
return FALSE;
}
}
} else {
/*
* High-bandwidth backdoor port not supported. Send the message, 4 bytes
* at a time. --hpreg
*/
for (;;) {
if (myBufSize == 0) {
/* We are done */
break;
}
/* IN: Type */
bp.in.cx.halfs.high = MESSAGE_TYPE_SENDPAYLOAD;
/* IN: Id and cookie */
bp.in.dx.halfs.high = chan->id;
bp.in.si.word = chan->cookieHigh;
bp.in.di.word = chan->cookieLow;
/* IN: Piece of message */
/*
* Beware in case we are not allowed to read extra bytes beyond the
* end of the buffer.
*/
switch (myBufSize) {
case 1:
bp.in.size = myBuf[0];
myBufSize -= 1;
break;
case 2:
bp.in.size = myBuf[0] | myBuf[1] << 8;
myBufSize -= 2;
break;
case 3:
bp.in.size = myBuf[0] | myBuf[1] << 8 | myBuf[2] << 16;
myBufSize -= 3;
break;
default:
bp.in.size = *(const uint32 *)myBuf;
myBufSize -= 4;
break;
}
bp.in.cx.halfs.low = BDOOR_CMD_MESSAGE;
Backdoor(&bp);
/* OUT: Status */
if ((bp.in.cx.halfs.high & MESSAGE_STATUS_SUCCESS) == 0) {
if ((bp.in.cx.halfs.high & MESSAGE_STATUS_CPT) != 0) {
/* A checkpoint occurred. Retry the operation. --hpreg */
goto retry;
}
MESSAGE_LOG("Message: Unable to send a message over the "
"communication channel %u\n", chan->id);
return FALSE;
}
myBuf += 4;
}
}
return TRUE;
}
/*
*-----------------------------------------------------------------------------
*
* Message_Receive --
*
* If vmware has posted a message for this channel, retrieve it
*
* Result:
* TRUE on success (bufSize is 0 if there is no message)
* FALSE on failure
*
* Side-effects:
* None
*
*-----------------------------------------------------------------------------
*/
Bool
Message_Receive(Message_Channel *chan, // IN/OUT
unsigned char **buf, // OUT
size_t *bufSize) // OUT
{
Backdoor_proto bp;
size_t myBufSize;
unsigned char *myBuf;
retry:
/*
* Is there a message waiting for our retrieval?
*/
/* IN: Type */
bp.in.cx.halfs.high = MESSAGE_TYPE_RECVSIZE;
/* IN: Id and cookie */
bp.in.dx.halfs.high = chan->id;
bp.in.si.word = chan->cookieHigh;
bp.in.di.word = chan->cookieLow;
bp.in.cx.halfs.low = BDOOR_CMD_MESSAGE;
Backdoor(&bp);
/* OUT: Status */
if ((bp.in.cx.halfs.high & MESSAGE_STATUS_SUCCESS) == 0) {
MESSAGE_LOG("Message: Unable to poll for messages over the "
"communication channel %u\n", chan->id);
return FALSE;
}
if ((bp.in.cx.halfs.high & MESSAGE_STATUS_DORECV) == 0) {
/* No message to retrieve */
*bufSize = 0;
return TRUE;
}
/*
* Receive the size.
*/
/* OUT: Type */
if (bp.in.dx.halfs.high != MESSAGE_TYPE_SENDSIZE) {
MESSAGE_LOG("Message: Protocol error. Expected a "
"MESSAGE_TYPE_SENDSIZE request from vmware\n");
return FALSE;
}
/* OUT: Size */
myBufSize = bp.out.bx.word;
/*
* Allocate an extra byte for a trailing NUL character. The code that will
* deal with this message may not know about binary strings, and may expect
* a C string instead. --hpreg
*/
if (myBufSize + 1 > chan->inAlloc) {
myBuf = (unsigned char *)realloc(chan->in, myBufSize + 1);
if (myBuf == NULL) {
MESSAGE_LOG("Message: Not enough memory to receive a message over "
"the communication channel %u\n", chan->id);
goto error_quit;
}
chan->in = myBuf;
chan->inAlloc = myBufSize + 1;
}
*bufSize = myBufSize;
myBuf = *buf = chan->in;
if (bp.in.cx.halfs.high & MESSAGE_STATUS_HB) {
/*
* High-bandwidth backdoor port supported. Receive the message in one
* backdoor operation. --hpreg
*/
if (myBufSize) {
Backdoor_proto_hb bphb;
bphb.in.bx.halfs.low = BDOORHB_CMD_MESSAGE;
bphb.in.bx.halfs.high = MESSAGE_STATUS_SUCCESS;
bphb.in.dx.halfs.high = chan->id;
bphb.in.srcAddr = chan->cookieHigh;
bphb.in.bp.word = chan->cookieLow;
bphb.in.size = myBufSize;
bphb.in.dstAddr = (uintptr_t) myBuf;
Backdoor_HbIn(&bphb);
if ((bphb.in.bx.halfs.high & MESSAGE_STATUS_SUCCESS) == 0) {
if ((bphb.in.bx.halfs.high & MESSAGE_STATUS_CPT) != 0) {
/* A checkpoint occurred. Retry the operation. --hpreg */
goto retry;
}
MESSAGE_LOG("Message: Unable to receive a message over the "
"communication channel %u\n", chan->id);
goto error_quit;
}
}
} else {
/*
* High-bandwidth backdoor port not supported. Receive the message, 4
* bytes at a time. --hpreg
*/
for (;;) {
if (myBufSize == 0) {
/* We are done */
break;
}
/* IN: Type */
bp.in.cx.halfs.high = MESSAGE_TYPE_RECVPAYLOAD;
/* IN: Id and cookie */
bp.in.dx.halfs.high = chan->id;
bp.in.si.word = chan->cookieHigh;
bp.in.di.word = chan->cookieLow;
/* IN: Status for the previous request (that succeeded) */
bp.in.size = MESSAGE_STATUS_SUCCESS;
bp.in.cx.halfs.low = BDOOR_CMD_MESSAGE;
Backdoor(&bp);
/* OUT: Status */
if ((bp.in.cx.halfs.high & MESSAGE_STATUS_SUCCESS) == 0) {
if ((bp.in.cx.halfs.high & MESSAGE_STATUS_CPT) != 0) {
/* A checkpoint occurred. Retry the operation. --hpreg */
goto retry;
}
MESSAGE_LOG("Message: Unable to receive a message over the "
"communication channel %u\n", chan->id);
goto error_quit;
}
/* OUT: Type */
if (bp.in.dx.halfs.high != MESSAGE_TYPE_SENDPAYLOAD) {
MESSAGE_LOG("Message: Protocol error. Expected a "
"MESSAGE_TYPE_SENDPAYLOAD from vmware\n");
goto error_quit;
}
/* OUT: Piece of message */
/*
* Beware in case we are not allowed to write extra bytes beyond the
* end of the buffer. --hpreg
*/
switch (myBufSize) {
case 1:
myBuf[0] = bp.out.bx.word & 0xff;
myBufSize -= 1;
break;
case 2:
myBuf[0] = bp.out.bx.word & 0xff;
myBuf[1] = (bp.out.bx.word >> 8) & 0xff;
myBufSize -= 2;
break;
case 3:
myBuf[0] = bp.out.bx.word & 0xff;
myBuf[1] = (bp.out.bx.word >> 8) & 0xff;
myBuf[2] = (bp.out.bx.word >> 16) & 0xff;
myBufSize -= 3;
break;
default:
*(uint32 *)myBuf = bp.out.bx.word;
myBufSize -= 4;
break;
}
myBuf += 4;
}
}
/* Write a trailing NUL just after the message. --hpreg */
chan->in[*bufSize] = '\0';
/* IN: Type */
bp.in.cx.halfs.high = MESSAGE_TYPE_RECVSTATUS;
/* IN: Id and cookie */
bp.in.dx.halfs.high = chan->id;
bp.in.si.word = chan->cookieHigh;
bp.in.di.word = chan->cookieLow;
/* IN: Status for the previous request (that succeeded) */
bp.in.size = MESSAGE_STATUS_SUCCESS;
bp.in.cx.halfs.low = BDOOR_CMD_MESSAGE;
Backdoor(&bp);
/* OUT: Status */
if ((bp.in.cx.halfs.high & MESSAGE_STATUS_SUCCESS) == 0) {
if ((bp.in.cx.halfs.high & MESSAGE_STATUS_CPT) != 0) {
/* A checkpoint occurred. Retry the operation. --hpreg */
goto retry;
}
MESSAGE_LOG("Message: Unable to receive a message over the "
"communication channel %u\n", chan->id);
goto error_quit;
}
return TRUE;
error_quit:
/* IN: Type */
if (myBufSize == 0) {
bp.in.cx.halfs.high = MESSAGE_TYPE_RECVSTATUS;
} else {
bp.in.cx.halfs.high = MESSAGE_TYPE_RECVPAYLOAD;
}
/* IN: Id and cookie */
bp.in.dx.halfs.high = chan->id;
bp.in.si.word = chan->cookieHigh;
bp.in.di.word = chan->cookieLow;
/* IN: Status for the previous request (that failed) */
bp.in.size = 0;
bp.in.cx.halfs.low = BDOOR_CMD_MESSAGE;
Backdoor(&bp);
/* OUT: Status */
if ((bp.in.cx.halfs.high & MESSAGE_STATUS_SUCCESS) == 0) {
MESSAGE_LOG("Message: Unable to signal an error of reception over the "
"communication channel %u\n", chan->id);
return FALSE;
}
return FALSE;
}
/*
*-----------------------------------------------------------------------------
*
* Message_Close --
*
* Close a communication channel
*
* Result:
* TRUE on success, the channel is destroyed
* FALSE on failure
*
* Side-effects:
* None
*
*-----------------------------------------------------------------------------
*/
Bool
Message_Close(Message_Channel *chan) // IN/OUT
{
Backdoor_proto bp;
Bool ret = TRUE;
/* IN: Type */
bp.in.cx.halfs.high = MESSAGE_TYPE_CLOSE;
/* IN: Id and cookie */
bp.in.dx.halfs.high = chan->id;
bp.in.si.word = chan->cookieHigh;
bp.in.di.word = chan->cookieLow;
bp.in.cx.halfs.low = BDOOR_CMD_MESSAGE;
Backdoor(&bp);
/* OUT: Status */
if ((bp.in.cx.halfs.high & MESSAGE_STATUS_SUCCESS) == 0) {
MESSAGE_LOG("Message: Unable to close the communication channel %u\n",
chan->id);
ret = FALSE;
}
free(chan->in);
chan->in = NULL;
free(chan);
return ret;
}
#ifdef __cplusplus
}
#endif

416
vendor/github.com/sigma/vmw-guestinfo/bridge/utilMem.c generated vendored Normal file
View File

@@ -0,0 +1,416 @@
/*********************************************************
* Copyright (C) 2009-2015 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation version 2.1 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*********************************************************/
/*
* utilMem.c --
*
* misc util functions
*/
#ifdef _WIN32
#include <windows.h>
#endif
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#include "vm_assert.h"
#include "util.h"
#ifdef __APPLE__
#include <TargetConditionals.h>
#if !defined TARGET_OS_IPHONE
#define TARGET_OS_IPHONE 0
#endif
#endif
static NORETURN void UtilAllocationFailure0(void);
static NORETURN void UtilAllocationFailure1(int bugNumber,
const char *file, int lineno);
static void
UtilAllocationFailure0(void)
{
Panic("Unrecoverable memory allocation failure\n");
}
static void
UtilAllocationFailure1(int bugNumber, const char *file, int lineno)
{
if (bugNumber == -1) {
Panic("Unrecoverable memory allocation failure at %s:%d\n",
file, lineno);
} else {
Panic("Unrecoverable memory allocation failure at %s:%d. Bug "
"number: %d\n", file, lineno, bugNumber);
}
}
/*
*-----------------------------------------------------------------------------
*
* UtilSafeMalloc0 --
* UtilSafeMalloc1 --
* Helper function for malloc
*
* Results:
* Pointer to the dynamically allocated memory.
*
* Side effects:
* May Panic if ran out of memory.
*
*-----------------------------------------------------------------------------
*/
void *
UtilSafeMalloc0(size_t size) // IN:
{
void *result = malloc(size);
if (result == NULL && size != 0) {
UtilAllocationFailure0();
}
return result;
}
void *
UtilSafeMalloc1(size_t size, // IN:
int bugNumber, // IN:
const char *file, // IN:
int lineno) // IN:
{
void *result = malloc(size);
if (result == NULL && size != 0) {
UtilAllocationFailure1(bugNumber, file, lineno);
}
return result;
}
/*
*-----------------------------------------------------------------------------
*
* UtilSafeRealloc0 --
* UtilSafeRealloc1 --
* Helper function for realloc
*
* Results:
* Pointer to the dynamically allocated memory.
*
* Side effects:
* May Panic if ran out of memory.
*
*-----------------------------------------------------------------------------
*/
void *
UtilSafeRealloc0(void *ptr, // IN:
size_t size) // IN:
{
void *result = realloc(ptr, size);
if (result == NULL && size != 0) {
UtilAllocationFailure0();
}
return result;
}
void *
UtilSafeRealloc1(void *ptr, // IN:
size_t size, // IN:
int bugNumber, // IN:
const char *file, // IN:
int lineno) // IN:
{
void *result = realloc(ptr, size);
if (result == NULL && size != 0) {
UtilAllocationFailure1(bugNumber, file, lineno);
}
return result;
}
/*
*-----------------------------------------------------------------------------
*
* UtilSafeCalloc0 --
* UtilSafeCalloc1 --
* Helper function for calloc
*
* Results:
* Pointer to the dynamically allocated memory.
*
* Side effects:
* May Panic if ran out of memory.
*
*-----------------------------------------------------------------------------
*/
void *
UtilSafeCalloc0(size_t nmemb, // IN:
size_t size) // IN:
{
void *result = calloc(nmemb, size);
if (result == NULL && nmemb != 0 && size != 0) {
UtilAllocationFailure0();
}
return result;
}
void *
UtilSafeCalloc1(size_t nmemb, // IN:
size_t size, // IN:
int bugNumber, // IN:
const char *file, // IN:
int lineno) // IN:
{
void *result = calloc(nmemb, size);
if (result == NULL && nmemb != 0 && size != 0) {
UtilAllocationFailure1(bugNumber, file, lineno);
}
return result;
}
/*
*-----------------------------------------------------------------------------
*
* Util_SafeStrdup --
* Helper function for strdup
*
* Results:
* Pointer to the dynamically allocated, duplicate string
*
* Side effects:
* May Panic if ran out of memory.
*
*-----------------------------------------------------------------------------
*/
char *
UtilSafeStrdup0(const char *s) // IN:
{
char *result;
if (s == NULL) {
return NULL;
}
#if defined(_WIN32)
if ((result = _strdup(s)) == NULL) {
#else
if ((result = strdup(s)) == NULL) {
#endif
UtilAllocationFailure0();
}
return result;
}
char *
UtilSafeStrdup1(const char *s, // IN:
int bugNumber, // IN:
const char *file, // IN:
int lineno) // IN:
{
char *result;
if (s == NULL) {
return NULL;
}
#if defined(_WIN32)
if ((result = _strdup(s)) == NULL) {
#else
if ((result = strdup(s)) == NULL) {
#endif
UtilAllocationFailure1(bugNumber, file, lineno);
}
return result;
}
/*
*-----------------------------------------------------------------------------
*
* Util_SafeStrndup --
*
* Returns a string consisting of first n characters of 's' if 's' has
* length >= 'n', otherwise returns a string duplicate of 's'.
*
* Results:
* Pointer to the duplicated string.
*
* Side effects:
* May Panic if ran out of memory.
*
*-----------------------------------------------------------------------------
*/
char *
UtilSafeStrndup0(const char *s, // IN:
size_t n) // IN:
{
size_t size;
char *copy;
const char *null;
size_t newSize;
if (s == NULL) {
return NULL;
}
null = memchr(s, '\0', n);
size = null ? (size_t)(null - s) : n;
newSize = size + 1;
if (newSize < size) { // Prevent integer overflow
copy = NULL;
} else {
copy = malloc(newSize);
}
if (copy == NULL) {
UtilAllocationFailure0();
}
copy[size] = '\0';
return (char *) memcpy(copy, s, size);
}
char *
UtilSafeStrndup1(const char *s, // IN:
size_t n, // IN:
int bugNumber, // IN:
const char *file, // IN:
int lineno) // IN:
{
size_t size;
char *copy;
const char *null;
size_t newSize;
if (s == NULL) {
return NULL;
}
null = memchr(s, '\0', n);
size = null ? (size_t)(null - s) : n;
newSize = size + 1;
if (newSize < size) { // Prevent integer overflow
copy = NULL;
} else {
copy = malloc(newSize);
}
if (copy == NULL) {
UtilAllocationFailure1(bugNumber, file, lineno);
}
copy[size] = '\0';
return (char *) memcpy(copy, s, size);
}
void *
Util_Memcpy(void *dest,
const void *src,
size_t count)
{
#if defined(__x86_64__) || defined(__i386__)
uintptr_t align = ((uintptr_t)dest | (uintptr_t)src | count);
#if defined __GNUC__
#if defined(__x86_64__)
size_t dummy0;
void *dummy1;
void *dummy2;
if ((align & 7) == 0) {
__asm__ __volatile__("\t"
"cld" "\n\t"
"rep ; movsq" "\n"
: "=c" (dummy0), "=D" (dummy1), "=S" (dummy2)
: "0" (count >> 3), "1" (dest), "2" (src)
: "memory", "cc"
);
return dest;
} else if ((align & 3) == 0) {
__asm__ __volatile__("\t"
"cld" "\n\t"
"rep ; movsd" "\n"
: "=c" (dummy0), "=D" (dummy1), "=S" (dummy2)
: "0" (count >> 2), "1" (dest), "2" (src)
: "memory", "cc"
);
return dest;
}
#elif defined(__i386__)
size_t dummy0;
void *dummy1;
void *dummy2;
if ((align & 3) == 0) {
__asm__ __volatile__("\t"
"cld" "\n\t"
"rep ; movsd" "\n"
: "=c" (dummy0), "=D" (dummy1), "=S" (dummy2)
: "0" (count >> 2), "1" (dest), "2" (src)
: "memory", "cc"
);
return dest;
}
#endif
#elif defined _MSC_VER
#if defined(__x86_64__)
if ((align & 7) == 0) {
__movsq((uint64 *)dest, (uint64 *)src, count >> 3);
return dest;
} else if ((align & 3) == 0) {
__movsd((unsigned long *)dest, (unsigned long *)src, count >> 2);
return dest;
}
#elif defined(__i386__)
if ((((uintptr_t)dest | (uintptr_t)src | count) & 3) == 0) {
__movsd((unsigned long *)dest, (unsigned long *)src, count >> 2);
return dest;
}
#endif
#endif
#endif
memcpy(dest, src, count);
return dest;
}

300
vendor/github.com/sigma/vmw-guestinfo/bridge/vmcheck.c generated vendored Normal file
View File

@@ -0,0 +1,300 @@
/*********************************************************
* Copyright (C) 2006-2015 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation version 2.1 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*********************************************************/
/*
* vmcheck.c --
*
* Utility functions for discovering our virtualization status.
*/
#include <stdlib.h>
#include <string.h>
#ifdef WINNT_DDK
# include <ntddk.h>
#endif
#include "vmware.h"
/*
* #include "vm_version.h"
* #include "vm_tools_version.h"
*/
#define VMX_TYPE_UNSET 0
#define VERSION_MAGIC 0x6
#if !defined(WINNT_DDK)
# include "hostinfo.h"
/* # include "str.h" */
# define Str_Strcmp(s1, s2) strcmp(s1, s2)
#endif
/*
* backdoor.h includes some files which redefine constants in ntddk.h. Ignore
* warnings about these redefinitions for WIN32 platform.
*/
#ifdef WINNT_DDK
#pragma warning (push)
// Warning: Conditional expression is constant.
#pragma warning( disable:4127 )
#endif
#include "backdoor.h"
#ifdef WINNT_DDK
#pragma warning (pop)
#endif
#include "backdoor_def.h"
#include "debug.h"
typedef Bool (*SafeCheckFn)(void);
#if !defined(_WIN32)
# include "vmsignal.h"
# include "setjmp.h"
static sigjmp_buf jmpBuf;
static Bool jmpIsSet;
/*
*----------------------------------------------------------------------
*
* VmCheckSegvHandler --
*
* Signal handler for segv. Return to the program state saved
* by a previous call to sigsetjmp, or Panic if sigsetjmp hasn't
* been called yet. This function never returns;
*
* Return Value:
* None.
*
* Side effects:
* See the manpage for sigsetjmp for details.
*
*----------------------------------------------------------------------
*/
static void
VmCheckSegvHandler(int clientData) // UNUSED
{
if (jmpIsSet) {
siglongjmp(jmpBuf, 1);
} else {
Panic("Received SEGV, exiting.");
}
}
#endif
/*
*----------------------------------------------------------------------
*
* VmCheckSafe --
*
* Calls a potentially unsafe function, trapping possible exceptions.
*
* Results:
*
* Return value of the passed function, or FALSE in case of exception.
*
* Side effects:
*
* Temporarily suppresses signals / SEH exceptions
*
*----------------------------------------------------------------------
*/
static Bool
VmCheckSafe(SafeCheckFn checkFn)
{
Bool result = FALSE;
/*
* On a real host this call should cause a GP and we catch
* that and set result to FALSE.
*/
#if defined(_WIN32)
__try {
result = checkFn();
} __except(EXCEPTION_EXECUTE_HANDLER) {
/* no op */
}
#else
do {
int signals[] = {
SIGILL,
SIGSEGV,
};
struct sigaction olds[ARRAYSIZE(signals)];
if (Signal_SetGroupHandler(signals, olds, ARRAYSIZE(signals),
VmCheckSegvHandler) == 0) {
Warning("%s: Failed to set signal handlers.\n", __FUNCTION__);
break;
}
if (sigsetjmp(jmpBuf, TRUE) == 0) {
jmpIsSet = TRUE;
result = checkFn();
} else {
jmpIsSet = FALSE;
}
if (Signal_ResetGroupHandler(signals, olds, ARRAYSIZE(signals)) == 0) {
Warning("%s: Failed to reset signal handlers.\n", __FUNCTION__);
}
} while (0);
#endif
return result;
}
/*
*----------------------------------------------------------------------
*
* VmCheck_GetVersion --
*
* Retrieve the version of VMware that's running on the
* other side of the backdoor.
*
* Return value:
* TRUE on success
* *version contains the VMX version
* *type contains the VMX type
* FALSE on failure
*
* Side effects:
* None
*
*----------------------------------------------------------------------
*/
Bool
VmCheck_GetVersion(uint32 *version, // OUT
uint32 *type) // OUT
{
Backdoor_proto bp;
ASSERT(version);
ASSERT(type);
/* Make sure EBX does not contain BDOOR_MAGIC */
bp.in.size = ~BDOOR_MAGIC;
/* Make sure ECX does not contain any known VMX type */
bp.in.cx.halfs.high = 0xFFFF;
bp.in.cx.halfs.low = BDOOR_CMD_GETVERSION;
Backdoor(&bp);
if (bp.out.ax.word == 0xFFFFFFFF) {
/*
* No backdoor device there. This code is not executing in a VMware
* virtual machine. --hpreg
*/
return FALSE;
}
if (bp.out.bx.word != BDOOR_MAGIC) {
return FALSE;
}
*version = bp.out.ax.word;
/*
* Old VMXs (workstation and express) didn't set their type. In that case,
* our special pattern will still be there. --hpreg
*/
/*
* Need to expand this out since the toolchain's gcc doesn't like mixing
* integral types and enums in the same trinary operator.
*/
if (bp.in.cx.halfs.high == 0xFFFF)
*type = VMX_TYPE_UNSET;
else
*type = bp.out.cx.word;
return TRUE;
}
/*
*----------------------------------------------------------------------
*
* VmCheck_IsVirtualWorld --
*
* Verify that we're running in a VM & we're version compatible with our
* environment.
*
* Return value:
* TRUE if we're in a virtual machine, FALSE otherwise.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
Bool
VmCheck_IsVirtualWorld(void)
{
uint32 version;
uint32 dummy;
#if !defined(WINNT_DDK)
if (VmCheckSafe(Hostinfo_TouchXen)) {
Debug("%s: detected Xen.\n", __FUNCTION__);
return FALSE;
}
if (VmCheckSafe(Hostinfo_TouchVirtualPC)) {
Debug("%s: detected Virtual PC.\n", __FUNCTION__);
return FALSE;
}
if (!VmCheckSafe(Hostinfo_TouchBackDoor)) {
Debug("%s: backdoor not detected.\n", __FUNCTION__);
return FALSE;
}
/* It should be safe to use the backdoor without a crash handler now. */
VmCheck_GetVersion(&version, &dummy);
#else
/*
* The Win32 vmwvaudio driver uses this function, so keep the old,
* VMware-only check.
*/
__try {
VmCheck_GetVersion(&version, &dummy);
} __except (GetExceptionCode() == STATUS_PRIVILEGED_INSTRUCTION) {
return FALSE;
}
#endif
if (version != VERSION_MAGIC) {
Debug("The version of this program is incompatible with your platform.\n");
return FALSE;
}
return TRUE;
}

123
vendor/github.com/sigma/vmw-guestinfo/bridge/vmsignal.c generated vendored Normal file
View File

@@ -0,0 +1,123 @@
/*********************************************************
* Copyright (C) 1998-2015 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation version 2.1 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*********************************************************/
/*
* vmsignal.c --
*
* Posix signal handling utility functions
*
*/
#ifndef VMX86_DEVEL
#endif
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include "vmsignal.h"
/*
* Signal_SetGroupHandler --
*
* Set a signal handler for a group of signals.
* We carefully ensure that if the handler is only used to handle the
* signals of the group, the handling of all the signals of the group is
* serialized, which means that the handler is not re-entrant.
*
* Return value:
* 1 on success
* 0 on failure (detail is displayed)
*
* Side effects:
* None
*
*/
int
Signal_SetGroupHandler(int const *signals, // IN
struct sigaction *olds, // OUT
unsigned int nr, // IN
void (*handler)(int signal)) // IN
{
unsigned int i;
struct sigaction new;
new.sa_handler = handler;
if (sigemptyset(&new.sa_mask)) {
fprintf(stderr, "Unable to empty a signal set: %s.\n\n", strerror(errno));
return 0;
}
for (i = 0; i < nr; i++) {
if (sigaddset(&new.sa_mask, signals[i])) {
fprintf(stderr, "Unable to add a signal to a signal set: %s.\n\n", strerror(errno));
return 0;
}
}
new.sa_flags = 0;
for (i = 0; i < nr; i++) {
if (sigaction(signals[i], &new, &olds[i])) {
fprintf(stderr, "Unable to modify the handler of the signal %d: %s.\n\n", signals[i], strerror(errno));
return 0;
}
}
return 1;
}
/*
* Signal_ResetGroupHandler --
*
* Reset the handler of each signal of a group of signals
*
* Return value:
* 1 on success
* 0 on failure (detail is displayed)
*
* Side effects:
* None
*
*/
int
Signal_ResetGroupHandler(int const *signals, // IN
struct sigaction const *olds, // IN
unsigned int nr) // IN
{
unsigned int i;
for (i = 0; i < nr; i++) {
if (sigaction(signals[i], &olds[i], NULL)) {
fprintf(stderr, "Unable to reset the handler of the signal %d: %s.\n\n", signals[i], strerror(errno));
return 0;
}
}
return 1;
}