Package: hw-detect Version: 1.107
Attached are changes to add a utility that detects if we are running in a VMware VM, and add open-vm-tools to the list of packages to be installed. Please consider adding it to hw-detect. Thanks, Oliver
diff --git a/.gitignore b/.gitignore index e2df58f..b53d8af 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ build-stamp configure-stamp archdetect archdetect-deb +checkvm *.o devnames-static.gz diff --git a/Makefile b/Makefile index 88a7582..ca5c70d 100644 --- a/Makefile +++ b/Makefile @@ -37,7 +37,7 @@ man1dir=$(DESTDIR)/usr/share/man/man1 INSTALL=install INSTALL_DATA = ${INSTALL} -m 644 -all: archdetect devnames-static.gz +all: checkvm archdetect devnames-static.gz test: set -e; for sh in *.sh; do sh -n $$sh; done @@ -46,9 +46,10 @@ clean: rm -f *~ rm -f *.o rm -f archdetect + rm -f checkvm rm -f devnames-static.gz -install: install-hw-detect install-ethdetect install-disk-detect install-driver-injection-disk-detect install-archdetect install-archdetect-deb +install: install-hw-detect install-ethdetect install-disk-detect install-driver-injection-disk-detect install-archdetect install-archdetect-deb install-checkvm install-hw-detect: hw-detect.sh $(INSTALL) -d $(bindir) @@ -79,6 +80,12 @@ endif else $(INSTALL) detect-stub.sh $(bindir)/hw-detect endif +ifeq ($(DEB_HOST_ARCH),i386) + $(INSTALL) checkvm $(bindir) +endif +ifeq ($(DEB_HOST_ARCH),amd64) + $(INSTALL) checkvm $(bindir) +endif install-ethdetect: ethdetect.sh $(INSTALL) -d $(bindir) $(netdir) @@ -97,6 +104,7 @@ install-archdetect: archdetect $(INSTALL) -d $(bindir) $(INSTALL) archdetect $(bindir) + install-archdetect-deb: archdetect $(INSTALL) -d $(bindir) $(INSTALL) archdetect $(bindir) @@ -109,5 +117,11 @@ archdetect: archdetect.o archdetect.o: %.o:%.c $(CC) $(CPPFLAGS) $(CFLAGS) $(CFLAGS_ARCH) -c $< +checkvm: checkvm.o + ${CC} ${LDFLAGS} -o $@ $^ + +checkvm.o: %.o:%.c + $(CC) $(CPPFLAGS) $(CFLAGS) $(CFLAGS_ARCH) -c $< + devnames-static.gz: devnames-static.txt grep -v '^#' $< | gzip -9c > $@ diff --git a/checkvm.c b/checkvm.c new file mode 100644 index 0000000..5e017b0 --- /dev/null +++ b/checkvm.c @@ -0,0 +1,146 @@ +#include <string.h> +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <signal.h> +#include <setjmp.h> + + +#define OC_CPU_X86_MMX (1<<0) +#define OC_CPU_X86_3DNOW (1<<1) +#define OC_CPU_X86_3DNOWEXT (1<<2) +#define OC_CPU_X86_MMXEXT (1<<3) +#define OC_CPU_X86_SSE (1<<4) +#define OC_CPU_X86_SSE2 (1<<5) +#define OC_CPU_X86_PNI (1<<6) +#define OC_CPU_X86_SSSE3 (1<<7) +#define OC_CPU_X86_SSE4_1 (1<<8) +#define OC_CPU_X86_SSE4_2 (1<<9) +#define OC_CPU_X86_SSE4A (1<<10) +#define OC_CPU_X86_SSE5 (1<<11) +#define OC_CPU_PPC_ALTIVEC (1<<12) + + +typedef unsigned int ogg_uint32_t; + +#if defined(i386) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_AMD64) +# if !defined(_MSC_VER) +# if defined(__amd64__)||defined(__x86_64__) +/*On x86-64, gcc seems to be able to figure out how to save %rbx for us when + compiling with -fPIC.*/ +# define cpuid(_op,_eax,_ebx,_ecx,_edx) \ + __asm__ __volatile__( \ + "cpuid\n\t" \ + :[eax]"=a"(_eax),[ebx]"=b"(_ebx),[ecx]"=c"(_ecx),[edx]"=d"(_edx) \ + :"a"(_op) \ + :"cc" \ + ) +# else +/*On x86-32, not so much.*/ +# define cpuid(_op,_eax,_ebx,_ecx,_edx) \ + __asm__ __volatile__( \ + "xchgl %%ebx,%[ebx]\n\t" \ + "cpuid\n\t" \ + "xchgl %%ebx,%[ebx]\n\t" \ + :[eax]"=a"(_eax),[ebx]"=r"(_ebx),[ecx]"=c"(_ecx),[edx]"=d"(_edx) \ + :"a"(_op) \ + :"cc" \ + ) +# endif +# endif +# endif + +int cpuid_check() +{ + ogg_uint32_t eax; + ogg_uint32_t ebx; + ogg_uint32_t ecx; + ogg_uint32_t edx; + char hyper_vendor_id[13]; + + cpuid(0x1, eax, ebx, ecx, edx); +// if (bit 31 of ecx is set) { + if (ecx & (1 << 30)) { + cpuid(0x40000000, eax, ebx, ecx, edx); + memcpy(hyper_vendor_id + 0, &ebx, 4); + memcpy(hyper_vendor_id + 4, &ecx, 4); + memcpy(hyper_vendor_id + 8, &edx, 4); + hyper_vendor_id[12] = '\0'; + if (!strcmp(hyper_vendor_id, "VMwareVMware")) + return 1; // Success - running under VMware + } + return 0; +} + +#define DMI_BIOS_SERIAL_PATH "/sys/devices/virtual/dmi/id/product_serial" + +int get_bios_serial(char *buf) +{ + FILE *fptr; + + if ((fptr = fopen(DMI_BIOS_SERIAL_PATH, "rt"))) { + int cnt; + cnt = fread(buf, 10, 1, fptr); + if (cnt < 0) { + return 1; + } + fclose(fptr); + } + return 0; +} + +int dmi_check(void) +{ + char string[10]; + get_bios_serial(string); + + if (!memcmp(string, "VMware-", 7) || !memcmp(string, "VMW", 3)) + return 1; // DMI contains VMware specific string. + else + return 0; +} + +#define VMWARE_HYPERVISOR_MAGIC 0x564D5868 +#define VMWARE_HYPERVISOR_PORT 0x5658 + +#define VMWARE_PORT_CMD_GETVERSION 10 + +#define UINT_MAX 0xffffffff + +#define VMWARE_PORT(cmd, eax, ebx, ecx, edx) \ + __asm__("inl (%%dx)" : \ + "=a"(eax), "=c"(ecx), "=d"(edx), "=b"(ebx) : \ + "0"(VMWARE_HYPERVISOR_MAGIC), \ + "1"(VMWARE_PORT_CMD_##cmd), \ + "2"(VMWARE_HYPERVISOR_PORT), "3"(UINT_MAX) : \ + "memory"); + +int hypervisor_port_check(void) +{ +// uint32_t eax, ebx, ecx, edx; + unsigned int eax, ebx, ecx, edx; + VMWARE_PORT(GETVERSION, eax, ebx, ecx, edx); + if (ebx == VMWARE_HYPERVISOR_MAGIC) + return 1; // Success - running under VMware + else + return 0; +} + +int Detect_VMware(void) +{ + if (cpuid_check()) { + printf("detected vm by cpu id\n"); + return 1; // Success running under VMware. + } else if (dmi_check() && hypervisor_port_check()) { + printf("detected vm by hypervisor port\n"); + return 2; + } + printf("not running in a vm\n"); + return 0; +} + +int main() +{ + exit(Detect_VMware() ? EXIT_SUCCESS : EXIT_FAILURE); +} + diff --git a/hw-detect.sh b/hw-detect.sh index 6f16a52..0f8c22e 100755 --- a/hw-detect.sh +++ b/hw-detect.sh @@ -531,6 +531,14 @@ case "$(udpkg --print-architecture)" in ;; esac +case "$(udpkg --print-architecture)" in + i386|amd64) + if checkvm ; then + apt-install open-vm-tools + fi + ;; +esac + db_progress SET $MAX_STEPS db_progress STOP