2021-02-03 15:59:42 +01:00
|
|
|
#include "cpuid.h"
|
|
|
|
#include "../libc/string.h"
|
|
|
|
#define INTEL_MAGIC_NUMBER 0x756e6547
|
|
|
|
#define AMD_MAGIC_NUMBER 0x68747541
|
|
|
|
#define UNRECOGNIZED_CPU 0xBADFF
|
|
|
|
|
|
|
|
static cpuid_t get_cpuid(icpuid_t cpu);
|
|
|
|
static icpuid_t detect_cpu(void);
|
|
|
|
static icpuid_t intel_cpu(void);
|
|
|
|
static icpuid_t amd_cpu(void);
|
|
|
|
static icpuid_t generic_cpu(void);
|
|
|
|
|
|
|
|
icpuid_t detect_cpu(void) {
|
|
|
|
uint32_t ebx, null;
|
|
|
|
icpuid_t i_cpu;
|
|
|
|
|
|
|
|
cpuid(0, null, ebx, null, null);
|
|
|
|
|
|
|
|
// Select CPU brand
|
|
|
|
switch(ebx) {
|
|
|
|
case INTEL_MAGIC_NUMBER:
|
|
|
|
i_cpu = intel_cpu();
|
|
|
|
break;
|
|
|
|
case AMD_MAGIC_NUMBER:
|
|
|
|
i_cpu = amd_cpu();
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
i_cpu = generic_cpu();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return i_cpu;
|
|
|
|
}
|
|
|
|
|
|
|
|
icpuid_t intel_cpu(void) {
|
|
|
|
uint32_t eax, ebx, null;
|
|
|
|
icpuid_t icpu;
|
|
|
|
|
|
|
|
// Fill the structure
|
|
|
|
cpuid(1, eax, ebx, null, null);
|
|
|
|
icpu.model = (eax >> 4) & 0xF;
|
|
|
|
icpu.family = (eax >> 8) & 0xF;
|
|
|
|
icpu.type = (eax >> 12) & 0xF;
|
|
|
|
icpu.brand = INTEL_MAGIC_NUMBER;
|
|
|
|
icpu.stepping = eax & 0xF;
|
|
|
|
icpu.reserved = eax >> 14;
|
|
|
|
|
|
|
|
return icpu;
|
|
|
|
}
|
|
|
|
|
|
|
|
icpuid_t amd_cpu(void) {
|
|
|
|
uint32_t eax, null;
|
|
|
|
icpuid_t icpu;
|
|
|
|
|
|
|
|
// Fill the structure
|
|
|
|
cpuid(1, eax, null, null, null);
|
|
|
|
icpu.model = (eax >> 4) & 0xF;
|
|
|
|
icpu.family = (eax >> 8) & 0xF;
|
|
|
|
icpu.stepping = eax & 0xF;
|
|
|
|
icpu.reserved = eax >> 12;
|
|
|
|
icpu.brand = AMD_MAGIC_NUMBER;
|
|
|
|
|
|
|
|
return icpu;
|
|
|
|
}
|
|
|
|
|
|
|
|
icpuid_t generic_cpu(void) {
|
|
|
|
icpuid_t icpu;
|
|
|
|
|
|
|
|
icpu.brand = UNRECOGNIZED_CPU; // Magic number for unknown CPUs
|
|
|
|
|
|
|
|
return icpu;
|
|
|
|
}
|
|
|
|
|
|
|
|
cpuid_t get_cpuid(icpuid_t cpu) {
|
|
|
|
cpuid_t cpuid;
|
|
|
|
uint8_t model[64];
|
|
|
|
|
|
|
|
// Recognize CPU brand
|
|
|
|
if(cpu.brand == AMD_MAGIC_NUMBER) {
|
|
|
|
switch(cpu.family) {
|
|
|
|
case 4:
|
|
|
|
strcpy(model, (uint8_t*)"486 model "); // Set model name
|
|
|
|
strcat(model, (void*)cpu.model); // Set model version
|
|
|
|
cpuid.model = model;
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
switch(cpu.model) {
|
|
|
|
case 0:
|
|
|
|
case 1:
|
|
|
|
case 2:
|
|
|
|
case 3:
|
|
|
|
case 4:
|
|
|
|
case 5:
|
|
|
|
case 6:
|
|
|
|
case 7:
|
|
|
|
strcpy(model, (uint8_t*)"K6 model "); // Set model name
|
|
|
|
strcat(model, (void*)cpu.model); // Set model version
|
|
|
|
cpuid.model = model;
|
|
|
|
break;
|
|
|
|
case 8:
|
|
|
|
strcpy(model, (uint8_t*)"K6-2 model "); // Set model name
|
|
|
|
strcat(model, (void*)cpu.model); // Set model version
|
|
|
|
cpuid.model = model;
|
|
|
|
break;
|
|
|
|
case 9:
|
|
|
|
strcpy(model, (uint8_t*)"K6-III model "); // Set model name
|
|
|
|
strcat(model, (void*)cpu.model); // Set model version
|
|
|
|
cpuid.model = model;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
strcpy(model, (uint8_t*)"K5/K6 model "); // Set model name
|
|
|
|
strcat(model, (void*)cpu.model); // Set model version
|
|
|
|
cpuid.model = model;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 6:
|
|
|
|
switch(cpu.model) {
|
|
|
|
case 1:
|
|
|
|
case 2:
|
|
|
|
case 3:
|
|
|
|
cpuid.model = (uint8_t*)"Duron model 3";
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
strcpy(model, (uint8_t*)"Athlon model ");
|
|
|
|
strcat(model, (void*)cpu.model);
|
|
|
|
cpuid.model = model;
|
|
|
|
break;
|
|
|
|
case 6:
|
|
|
|
cpuid.model = (uint8_t*)"Athlon MP/Mobile Athlon Model 6";
|
|
|
|
break;
|
|
|
|
case 7:
|
|
|
|
cpuid.model = (uint8_t*)"Mobile Duron Model 7";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
strcpy(model, (uint8_t*)"Duron/Athlon model ");
|
|
|
|
strcat(model, (void*)cpu.model);
|
|
|
|
cpuid.model = model;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else if(cpu.brand == INTEL_MAGIC_NUMBER) {
|
|
|
|
switch(cpu.type) {
|
|
|
|
case 0:
|
|
|
|
cpuid.type =(uint8_t*)"Original OEM";
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
cpuid.type = (uint8_t*)"Overdrive";
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
cpuid.type = (uint8_t*)"Dual-capable";
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
cpuid.type = (uint8_t*)"Reserved";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch(cpu.family) {
|
|
|
|
case 3:
|
|
|
|
cpuid.family = (uint8_t*)"i386";
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
cpuid.family = (uint8_t*)"i486";
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
cpuid.family = (uint8_t*)"Pentium II Model 5/Xeon/Celeron";
|
|
|
|
break;
|
|
|
|
case 6:
|
|
|
|
cpuid.family = (uint8_t*)"Pentium Pro";
|
|
|
|
break;
|
|
|
|
case 15:
|
|
|
|
cpuid.family = (uint8_t*)"Pentium 4";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else if(cpu.brand == UNRECOGNIZED_CPU)
|
|
|
|
cpuid.family = (uint8_t*)"Generic (x86) CPU";
|
|
|
|
|
|
|
|
return cpuid;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t *get_cpu_type() {
|
|
|
|
icpuid_t icpu = detect_cpu(); // Detect CPU brand(Intel, AMD or generic x86)
|
|
|
|
cpuid_t cpu_type = get_cpuid(icpu);
|
|
|
|
|
|
|
|
return (uint8_t*)cpu_type.type;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t *get_cpu_family() {
|
|
|
|
icpuid_t icpu = detect_cpu(); // Detect CPU brand(Intel, AMD or generic x86)
|
|
|
|
cpuid_t cpu_family = get_cpuid(icpu);
|
|
|
|
|
|
|
|
return (uint8_t*)cpu_family.family;
|
|
|
|
|
|
|
|
}
|