272
vendor/github.com/sigma/vmw-guestinfo/bridge/backdoor.c
generated
vendored
Normal file
272
vendor/github.com/sigma/vmw-guestinfo/bridge/backdoor.c
generated
vendored
Normal 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
|
||||
235
vendor/github.com/sigma/vmw-guestinfo/bridge/backdoor_386.c
generated
vendored
Normal file
235
vendor/github.com/sigma/vmw-guestinfo/bridge/backdoor_386.c
generated
vendored
Normal 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
|
||||
|
||||
243
vendor/github.com/sigma/vmw-guestinfo/bridge/backdoor_amd64.c
generated
vendored
Normal file
243
vendor/github.com/sigma/vmw-guestinfo/bridge/backdoor_amd64.c
generated
vendored
Normal 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
60
vendor/github.com/sigma/vmw-guestinfo/bridge/bridge.go
generated
vendored
Normal 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
439
vendor/github.com/sigma/vmw-guestinfo/bridge/dynbuf.c
generated
vendored
Normal 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
336
vendor/github.com/sigma/vmw-guestinfo/bridge/hostinfo.c
generated
vendored
Normal 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], ®);
|
||||
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], ®);
|
||||
|
||||
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;
|
||||
* }
|
||||
*/
|
||||
|
||||
686
vendor/github.com/sigma/vmw-guestinfo/bridge/hostinfoHV.c
generated
vendored
Normal file
686
vendor/github.com/sigma/vmw-guestinfo/bridge/hostinfoHV.c
generated
vendored
Normal 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, ®s);
|
||||
if (!CPUID_ISSET(1, ECX, HYPERVISOR, regs.ecx)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
regs.ebx = 0;
|
||||
regs.ecx = 0;
|
||||
regs.edx = 0;
|
||||
|
||||
__GET_CPUID(0x40000000, ®s);
|
||||
|
||||
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
605
vendor/github.com/sigma/vmw-guestinfo/bridge/message.c
generated
vendored
Normal 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
416
vendor/github.com/sigma/vmw-guestinfo/bridge/utilMem.c
generated
vendored
Normal 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
300
vendor/github.com/sigma/vmw-guestinfo/bridge/vmcheck.c
generated
vendored
Normal 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
123
vendor/github.com/sigma/vmw-guestinfo/bridge/vmsignal.c
generated
vendored
Normal 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;
|
||||
}
|
||||
Reference in New Issue
Block a user