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
27static int
28xtoi(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
71int
72main(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