int read_hypervisor_dmi(void) { int rc = HYPER_NONE; uint8_t *buf = NULL; size_t fp = 0; if (sizeof(uint8_t) != 1 || sizeof(uint16_t) != 2 || sizeof(uint32_t) != 4 || '\0' != 0) return rc; rc = hypervisor_decode_sysfw(); if (rc >= 0) return rc; /* First try EFI (ia64, Intel-based Mac) */ switch (address_from_efi(&fp)) { case EFI_NOT_FOUND: goto memory_scan; case EFI_NO_SMBIOS: goto done; } buf = get_mem_chunk(fp, 0x20, _PATH_DEV_MEM); if (!buf) goto done; rc = hypervisor_decode_smbios(buf, _PATH_DEV_MEM); if (rc) goto done; free(buf); buf = NULL; memory_scan: #if defined(__x86_64__) || defined(__i386__) /* Fallback to memory scan (x86, x86_64) */ buf = get_mem_chunk(0xF0000, 0x10000, _PATH_DEV_MEM); if (!buf) goto done; for (fp = 0; fp <= 0xFFF0; fp += 16) { if (memcmp(buf + fp, "_SM_", 4) == 0 && fp <= 0xFFE0) { rc = hypervisor_decode_smbios(buf + fp, _PATH_DEV_MEM); if (rc == -1) fp += 16; } else if (memcmp(buf + fp, "_DMI_", 5) == 0) rc = hypervisor_decode_legacy(buf + fp, _PATH_DEV_MEM); if (rc >= 0) break; } #endif done: free(buf); return rc; }
int read_hypervisor_dmi(void) { int ret = HYPER_NONE; uint8_t *buf = NULL; size_t fp = 0; if (sizeof(uint8_t) != 1 || sizeof(uint16_t) != 2 || sizeof(uint32_t) != 4 || '\0' != 0) return ret; /* First try EFI (ia64, Intel-based Mac) */ switch (address_from_efi(&fp)) { case EFI_NOT_FOUND: goto memory_scan; case EFI_NO_SMBIOS: goto exit_free; } buf = get_mem_chunk(fp, 0x20, _PATH_DEV_MEM); if (!buf) goto exit_free; if (hypervisor_decode_smbios(buf, _PATH_DEV_MEM)) goto done; memory_scan: /* Fallback to memory scan (x86, x86_64) */ buf = get_mem_chunk(0xF0000, 0x10000, _PATH_DEV_MEM); if (!buf) goto exit_free; for (fp = 0; fp <= 0xFFF0; fp += 16) { if (memcmp(buf + fp, "_SM_", 4) == 0 && fp <= 0xFFE0) { if ((ret = hypervisor_decode_smbios(buf + fp, _PATH_DEV_MEM)) == -1) fp += 16; } else if (memcmp(buf + fp, "_DMI_", 5) == 0) ret = hypervisor_decode_legacy(buf + fp, _PATH_DEV_MEM); } done: free(buf); exit_free: return ret; }
static int hypervisor_from_dmi_table(uint32_t base, uint16_t len, uint16_t num, const char *devmem) { uint8_t *buf; uint8_t *data; int i = 0; char *vendor = NULL; char *product = NULL; char *manufacturer = NULL; int rc = HYPER_NONE; data = buf = get_mem_chunk(base, len, devmem); if (!buf) goto done; /* 4 is the length of an SMBIOS structure header */ while (i < num && data + 4 <= buf + len) { uint8_t *next; struct dmi_header h; to_dmi_header(&h, data); /* * If a short entry is found (less than 4 bytes), not only it * is invalid, but we cannot reliably locate the next entry. * Better stop at this point. */ if (h.length < 4) goto done; /* look for the next handle */ next = data + h.length; while (next - buf + 1 < len && (next[0] != 0 || next[1] != 0)) next++; next += 2; switch (h.type) { case 0: vendor = dmi_string(&h, data[0x04]); break; case 1: manufacturer = dmi_string(&h, data[0x04]); product = dmi_string(&h, data[0x05]); break; default: break; } data = next; i++; } if (manufacturer && !strcmp(manufacturer, "innotek GmbH")) rc = HYPER_INNOTEK; else if (manufacturer && strstr(manufacturer, "HITACHI") && product && strstr(product, "LPAR")) rc = HYPER_HITACHI; else if (vendor && !strcmp(vendor, "Parallels")) rc = HYPER_PARALLELS; done: free(buf); return rc; }