-
Notifications
You must be signed in to change notification settings - Fork 8
/
vmware-detect.c
122 lines (94 loc) · 2.63 KB
/
vmware-detect.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#define VMWARE_HYPERVISOR_MAGIC 0x564D5868
#define VMWARE_HYPERVISOR_PORT 0x5658
#define VMWARE_PORT_CMD_GETVERSION 10
#define VMWARE_PORT_CMD_GETDEVICE 11
#define VMWARE_PORT_CMD_GETHWMODELVER 17
#define VMWARE_MAX_DEVICES 50
#define VMWARE_PORT(cmd, eax, ebx, ecx, edx) \
__asm__("inl %%dx, %%eax" : \
"=a"(eax), "=c"(ecx), "=d"(edx), "=b"(ebx) : \
"0"(VMWARE_HYPERVISOR_MAGIC), \
"1"(VMWARE_PORT_CMD_##cmd), \
"2"(VMWARE_HYPERVISOR_PORT), "3"(ebx) : \
"memory");
static bool vmware_hypervisor_port_check(void)
{
uint32_t eax, ebx, ecx, edx;
ebx = UINT_MAX;
VMWARE_PORT(GETVERSION, eax, ebx, ecx, edx);
if (ebx == VMWARE_HYPERVISOR_MAGIC)
return true;
return false;
}
static bool vmware_check(void)
{
if (!cpuid_scan("VMwareVMware"))
return false;
return vmware_hypervisor_port_check();
}
struct vmware_device {
char devname[32];
uint32_t devid;
bool enabled;
char pad[3];
};
static bool vmware_read_device_chunk(uint16_t id, uint16_t offset, uint32_t *data)
{
uint32_t eax, ebx, ecx, edx;
ebx = (id << 16) | offset;
VMWARE_PORT(GETDEVICE, eax, ebx, ecx, edx);
if (eax == 0)
return false;
*data = ebx;
return true;
}
static bool vmware_read_device(uint16_t id, struct vmware_device *dev)
{
uint16_t step;
uint32_t *p;
for (step = 0, p = (uint32_t *) dev; step < sizeof(struct vmware_device); step += sizeof(uint32_t), p++)
if (!vmware_read_device_chunk(id, step, p))
return false;
return true;
}
static void vmware_enum_devices(void)
{
uint16_t i;
for (i = 0; i < VMWARE_MAX_DEVICES; i++)
{
struct vmware_device dev = { };
if (!vmware_read_device(i, &dev))
continue;
if (*dev.devname == '\0')
continue;
printf("Device %d: %s (%s)\n", i, dev.devname, dev.enabled ? "enabled" : "disabled");
}
}
static const char *vmware_types[] = {
"Unknown / Not Set",
"???",
"ESX/ESXi Server",
"???",
"Workstation",
};
static void vmware_explain(void)
{
uint32_t eax, ebx, ecx, edx;
VMWARE_PORT(GETVERSION, eax, ebx, ecx, edx);
if (ebx != VMWARE_HYPERVISOR_MAGIC)
abort();
printf("Hypervisor: VMware (protocol %d)\n", eax);
if (ecx != 0)
printf("Product: %s\n", vmware_types[ecx]);
vmware_enum_devices();
VMWARE_PORT(GETHWMODELVER, eax, ebx, ecx, edx);
if (ebx != VMWARE_HYPERVISOR_MAGIC)
return;
if (eax != -1)
printf("Hardware Model: %d\n", eax);
}
static struct test_impl vmware_impl = {
.hv_name = "VMware",
.check = vmware_check,
.explain = vmware_explain,
};