xref: /haiku/src/tools/cpuidtool.c (revision 1026b0a1a76dc88927bb8175c470f638dc5464ee)
1 /*
2  * Copyright 2012 Haiku, Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Alexander von Gluck, kallisti5@unixzen.com
7  */
8 
9 /*
10  * Pass a standard CPUID in hex, and get out a CPUID for OS.h
11  */
12 
13 
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 
18 
19 #define EXT_FAMILY_MASK 0xF00000
20 #define EXT_MODEL_MASK	0x0F0000
21 #define FAMILY_MASK		0x000F00
22 #define MODEL_MASK		0x0000F0
23 #define STEPPING_MASK	0x00000F
24 
25 
26 // Converts a hexadecimal string to integer
27 static int
28 xtoi(const char* xs, unsigned int* result)
29 {
30 	size_t szlen = strlen(xs);
31 	int i;
32 	int xv;
33 	int fact;
34 
35 	if (szlen > 0) {
36 		// Converting more than 32bit hexadecimal value?
37 		if (szlen > 8)
38 			return 2;
39 
40 		// Begin conversion here
41 		*result = 0;
42 		fact = 1;
43 
44 		// Run until no more character to convert
45 		for (i = szlen - 1; i>=0; i--) {
46 			if (isxdigit(*(xs + i))) {
47 				if (*(xs + i) >= 97)
48 					xv = (*(xs + i) - 97) + 10;
49 				else if (*(xs + i) >= 65)
50 					xv = (*(xs + i) - 65) + 10;
51 				else
52 					xv = *(xs + i) - 48;
53 
54 				*result += (xv * fact);
55 				fact *= 16;
56 			} else {
57 				// Conversion was abnormally terminated
58 				// by non hexadecimal digit, hence
59 				// returning only the converted with
60 				// an error value 4 (illegal hex character)
61 				return 4;
62 			}
63 		}
64 	}
65 
66 	// Nothing to convert
67 	return 1;
68 }
69 
70 
71 int
72 main(int argc, char *argv[])
73 {
74 	if (argc != 3) {
75 		printf("Provide the cpuid in hex, and you will get how we id it\n");
76 		printf("usage: cpuidhaiku <AMD|INTEL> <cpuid_hex>\n");
77 		return 1;
78 	}
79 
80 	unsigned int cpuid = 0;
81 	xtoi(argv[2], &cpuid);
82 
83 	printf("cpuid: 0x%X\n", cpuid);
84 
85 	unsigned int extFam = (cpuid & EXT_FAMILY_MASK) >> 20;
86 	unsigned int extMod = (cpuid & EXT_MODEL_MASK) >> 16;
87 	unsigned int family = (cpuid & FAMILY_MASK) >> 8;
88 	unsigned int model = (cpuid & MODEL_MASK) >> 4;
89 	unsigned int stepping = (cpuid & STEPPING_MASK);
90 
91 	unsigned int cpuidHaiku;
92 	if (strncmp(argv[1], "AMD", 3) == 0) {
93 		if (family == 0xF) {
94 			cpuidHaiku = (extFam << 20) + (extMod << 16)
95 				+ (family << 4) + model;
96 		} else
97 			cpuidHaiku = (family << 4) + model;
98 		cpuidHaiku += 0x1100; // AMD vendor id
99 	} else if (strncmp(argv[1], "INTEL", 5) == 0) {
100 		cpuidHaiku = (extFam << 20) + (extMod << 16)
101 			+ (family << 4) + model;
102 		cpuidHaiku += 0x1000; // Intel vendor id
103 	} else {
104 		printf("Vendor should be AMD or INTEL\n");
105 		return 1;
106 	}
107 
108 	printf("Haiku CPUID: 0x%lx\n", cpuidHaiku);
109 
110 	return 0;
111 }
112