3 * Copyright (C) 2010, 2011 IPFire Team (www.ipfire.org)
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include <linux/hdreg.h>
26 #include <sys/ioctl.h>
28 /* hypervisor vendors */
36 HYPER_LAST
/* for loop - must be last*/
39 const char *hypervisor_ids
[] = {
41 [HYPER_XEN
] = "XenVMMXenVMM",
42 [HYPER_KVM
] = "KVMKVMKVM",
43 /* http://msdn.microsoft.com/en-us/library/ff542428.aspx */
44 [HYPER_MSHV
] = "Microsoft Hv",
45 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
46 [HYPER_VMWARE
] = "VMwareVMware",
50 const char *hypervisor_vendors
[] = {
54 [HYPER_MSHV
] = "Microsoft",
55 [HYPER_VMWARE
] = "VMWare",
56 [HYPER_OTHER
] = "other"
59 #define NEWLINE "\n\r"
61 static void truncate_nl(char *s
) {
64 s
[strcspn(s
, NEWLINE
)] = '\0';
67 static int read_one_line_file(const char *filename
, char **line
) {
70 if (!filename
|| !line
)
73 FILE* f
= fopen(filename
, "re");
77 if (!fgets(t
, sizeof(t
), f
)) {
79 return errno
? -errno
: -EIO
;
95 * This CPUID leaf returns the information about the hypervisor.
96 * EAX : maximum input value for CPUID supported by the hypervisor.
97 * EBX, ECX, EDX : Hypervisor vendor ID signature. E.g. VMwareVMware.
99 #define HYPERVISOR_INFO_LEAF 0x40000000
101 int detect_hypervisor(int *hypervisor
) {
102 #if defined(__x86_64__) || defined(__i386__)
103 /* Try high-level hypervisor sysfs file first: */
105 int r
= read_one_line_file("/sys/hypervisor/type", &hvtype
);
107 if (strcmp(hvtype
, "xen") == 0) {
108 *hypervisor
= HYPER_XEN
;
111 } else if (r
!= -ENOENT
)
114 /* http://lwn.net/Articles/301888/ */
116 #if defined(__amd64__)
119 #elif defined(__i386__)
131 __asm__
__volatile__ (
132 /* ebx/rbx is being used for PIC! */
133 " push %%"REG_b
" \n\t"
135 " pop %%"REG_b
" \n\t"
137 : "=a" (eax
), "=c" (ecx
)
141 bool has_hypervisor
= !!(ecx
& 0x80000000U
);
143 if (has_hypervisor
) {
144 /* There is a hypervisor, see what it is... */
146 __asm__
__volatile__ (
147 " push %%"REG_b
" \n\t"
149 " mov %%ebx, %1 \n\t"
150 " pop %%"REG_b
" \n\t"
152 : "=a" (eax
), "=r" (sig
.sig32
[0]), "=c" (sig
.sig32
[1]), "=d" (sig
.sig32
[2])
157 *hypervisor
= HYPER_OTHER
;
160 for (int id
= HYPER_NONE
+ 1; id
< HYPER_LAST
; id
++) {
161 if (strcmp(hypervisor_ids
[id
], sig
.text
) == 0) {
175 do_detect_hypervisor() {
177 Get hypervisor from the cpuid command.
179 int hypervisor
= HYPER_NONE
;
181 int r
= detect_hypervisor(&hypervisor
);
183 const char* hypervisor_vendor
= hypervisor_vendors
[hypervisor
];
184 if (!hypervisor_vendor
)
187 return PyUnicode_FromString(hypervisor_vendor
);
194 do_get_harddisk_serial(PyObject
*o
, PyObject
*args
) {
196 Python wrapper around read_harddisk_serial.
198 static struct hd_driveid hd
;
199 const char *device
= NULL
;
202 if (!PyArg_ParseTuple(args
, "s", &device
))
205 int fd
= open(device
, O_RDONLY
| O_NONBLOCK
);
207 PyErr_Format(PyExc_OSError
, "Could not open block device: %s", device
);
211 if (!ioctl(fd
, HDIO_GET_IDENTITY
, &hd
)) {
212 snprintf(serial
, sizeof(serial
) - 1, "%s", (const char *)hd
.serial_no
);
216 return PyUnicode_FromString(serial
);
225 static PyMethodDef fireinfo_methods
[] = {
226 { "detect_hypervisor", (PyCFunction
) do_detect_hypervisor
, METH_NOARGS
, NULL
},
227 { "get_harddisk_serial", (PyCFunction
) do_get_harddisk_serial
, METH_VARARGS
, NULL
},
228 { NULL
, NULL
, 0, NULL
}
231 static struct PyModuleDef fireinfo_module
= {
232 .m_base
= PyModuleDef_HEAD_INIT
,
233 .m_name
= "_fireinfo",
235 .m_doc
= "Python module for fireinfo",
236 .m_methods
= fireinfo_methods
,
239 PyMODINIT_FUNC
PyInit__fireinfo(void) {
240 PyObject
* m
= PyModule_Create(&fireinfo_module
);