]>
Commit | Line | Data |
---|---|---|
1 | #define _GNU_SOURCE /* we want memmem() */ | |
2 | #include <stdio.h> | |
3 | #include <stdlib.h> | |
4 | #include <string.h> | |
5 | #include <unistd.h> | |
6 | #include <signal.h> | |
7 | #include <ctype.h> | |
8 | ||
9 | #include <sys/types.h> | |
10 | #include <sys/wait.h> | |
11 | ||
12 | #include "hd.h" | |
13 | #include "hd_int.h" | |
14 | #include "sys.h" | |
15 | ||
16 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
17 | * general system info | |
18 | * | |
19 | * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
20 | */ | |
21 | ||
22 | #if defined(__i386__) | |
23 | static void sigsegv_handler(int signum); | |
24 | static void chk_vmware(hd_data_t *hd_data, sys_info_t *st); | |
25 | #endif | |
26 | ||
27 | #if defined(__i386__) || defined(__x86_64__) | |
28 | static int is_txt(char c); | |
29 | static int is_decimal(char c); | |
30 | static int txt_len(char *s); | |
31 | static int decimal_len(char *s); | |
32 | static int chk_vaio(hd_data_t *hd_data, sys_info_t *st); | |
33 | #ifdef UCLIBC | |
34 | void *memmem(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen); | |
35 | #endif | |
36 | #endif | |
37 | ||
38 | void hd_scan_sys(hd_data_t *hd_data) | |
39 | { | |
40 | hd_t *hd; | |
41 | sys_info_t *st; | |
42 | #if defined(__PPC__) || defined(__sparc__) | |
43 | char buf0[80], *s, *t; | |
44 | str_list_t *sl; | |
45 | #endif | |
46 | ||
47 | if(!hd_probe_feature(hd_data, pr_sys)) return; | |
48 | ||
49 | hd_data->module = mod_sys; | |
50 | ||
51 | /* some clean-up */ | |
52 | remove_hd_entries(hd_data); | |
53 | ||
54 | PROGRESS(1, 0, "cpu"); | |
55 | ||
56 | hd = add_hd_entry(hd_data, __LINE__, 0); | |
57 | hd->base_class.id = bc_internal; | |
58 | hd->sub_class.id = sc_int_sys; | |
59 | hd->detail = new_mem(sizeof *hd->detail); | |
60 | hd->detail->type = hd_detail_sys; | |
61 | hd->detail->sys.data = st = new_mem(sizeof *st); | |
62 | ||
63 | if(!hd_data->cpu) { | |
64 | hd_data->cpu = read_file(PROC_CPUINFO, 0, 0); | |
65 | } | |
66 | ||
67 | #ifdef __PPC__ | |
68 | for(sl = hd_data->cpu; sl; sl = sl->next) { | |
69 | if(sscanf(sl->str, "motherboard : %79[^\n]", buf0) == 1) { | |
70 | if((s = strstr(buf0, "MacRISC"))) { | |
71 | for(t = s + sizeof "MacRISC" - 1; isalnum(*t); t++); | |
72 | *t = 0; | |
73 | st->system_type = new_str(s); | |
74 | hd_data->flags.no_parport = 1; | |
75 | } | |
76 | } | |
77 | if(sscanf(sl->str, "machine : %79[^\n]", buf0) == 1) { | |
78 | if(strstr(buf0, "PReP")) { | |
79 | st->system_type = new_str("PReP"); | |
80 | } | |
81 | else if(strstr(buf0, "CHRP")) { | |
82 | st->system_type = new_str(/* is_64 ? "CHRP64" : */ "CHRP"); | |
83 | } | |
84 | else if(strstr(buf0, "iSeries")) { | |
85 | st->system_type = new_str("iSeries"); | |
86 | hd_data->flags.iseries = 1; | |
87 | } | |
88 | if(strstr(buf0, "PowerBook2,")) { | |
89 | st->model = new_str("iBook"); | |
90 | } | |
91 | else if(strstr(buf0, "PowerBook")) { | |
92 | st->model = new_str("PowerBook"); | |
93 | } | |
94 | } | |
95 | if(sscanf(sl->str, "pmac-generation : %79[^\n]", buf0) == 1) { | |
96 | st->generation = new_str(buf0); | |
97 | } | |
98 | } | |
99 | #endif /* __PPC__ */ | |
100 | ||
101 | #ifdef __sparc__ | |
102 | for(sl = hd_data->cpu; sl; sl = sl->next) { | |
103 | if(sscanf(sl->str, "type : %79[^\n]", buf0) == 1) { | |
104 | st->system_type = new_str(buf0); | |
105 | } | |
106 | } | |
107 | #endif | |
108 | ||
109 | #if defined(__i386__) || defined(__x86_64__) | |
110 | chk_vaio(hd_data, st); | |
111 | #endif | |
112 | ||
113 | #if defined(__i386__) | |
114 | chk_vmware(hd_data, st); | |
115 | #endif | |
116 | ||
117 | if(st->vendor) hd->vendor.name = new_str(st->vendor); | |
118 | if(st->model) hd->device.name = new_str(st->model); | |
119 | if(st->serial) hd->serial = new_str(st->serial); | |
120 | } | |
121 | ||
122 | #if defined(__i386__) | |
123 | void sigsegv_handler(int signum) { exit(77); } | |
124 | ||
125 | void chk_vmware(hd_data_t *hd_data, sys_info_t *st) | |
126 | { | |
127 | static int is_vmware = -1; | |
128 | int child, status; | |
129 | ||
130 | /* do the check only once */ | |
131 | if(is_vmware < 0) { | |
132 | ||
133 | child = fork(); | |
134 | ||
135 | if(child == 0) { | |
136 | signal(SIGSEGV, sigsegv_handler); | |
137 | ||
138 | asm( | |
139 | "push %ebx\n" | |
140 | "\tpush %edx\n" | |
141 | "\tpush %eax\n" | |
142 | "\tpush %ecx\n" | |
143 | "\tmov $0x564d5868,%eax\n" | |
144 | "\tmov $0xa,%ecx\n" | |
145 | "\tmov $0x5658,%edx\n" | |
146 | "\tin (%dx),%eax\n" | |
147 | "\tpop %ecx\n" | |
148 | "\tpop %eax\n" | |
149 | "\tpop %edx\n" | |
150 | "\tpop %ebx\n" | |
151 | ); | |
152 | ||
153 | _exit(66); | |
154 | } | |
155 | else { | |
156 | if(waitpid(child, &status, 0) == child) { | |
157 | status = WEXITSTATUS(status); | |
158 | if(status == 66) is_vmware = 1; | |
159 | if(status == 77) is_vmware = 0; | |
160 | } | |
161 | } | |
162 | ||
163 | ADD2LOG(" vmware check: %d\n", is_vmware); | |
164 | } | |
165 | ||
166 | if(is_vmware == 1) { | |
167 | st->model = new_str("VMWare"); | |
168 | } | |
169 | ||
170 | hd_data->in_vmware = is_vmware; | |
171 | } | |
172 | ||
173 | #endif /* __i386__ */ | |
174 | ||
175 | ||
176 | #if defined(__i386__) || defined(__x86_64__) | |
177 | int is_txt(char c) | |
178 | { | |
179 | if(c < ' ' || c == 0x7f) return 0; | |
180 | ||
181 | return 1; | |
182 | } | |
183 | ||
184 | int is_decimal(char c) | |
185 | { | |
186 | if(c < '0' || c > '9') return 0; | |
187 | ||
188 | return 1; | |
189 | } | |
190 | ||
191 | int txt_len(char *s) | |
192 | { | |
193 | int i; | |
194 | ||
195 | for(i = 0; i < 0x100; i++) { | |
196 | if(!is_txt(s[i])) break; | |
197 | } | |
198 | ||
199 | return i; | |
200 | } | |
201 | ||
202 | int decimal_len(char *s) | |
203 | { | |
204 | int i; | |
205 | ||
206 | for(i = 0; i < 0x100; i++) { | |
207 | if(!is_decimal(s[i])) break; | |
208 | } | |
209 | ||
210 | return i; | |
211 | } | |
212 | ||
213 | int chk_vaio(hd_data_t *hd_data, sys_info_t *st) | |
214 | { | |
215 | int i; | |
216 | unsigned char *data, *s, *s0, *s1; | |
217 | ||
218 | if(!hd_data->bios_rom.data) return 0; | |
219 | ||
220 | data = hd_data->bios_rom.data + 0xe8000 - hd_data->bios_rom.start; | |
221 | ||
222 | if(!(s = memmem(data, 0x10000, "Sony Corp", sizeof "Sony Corp" - 1))) return 0; | |
223 | ||
224 | if((i = txt_len(s))) st->vendor = canon_str(s, i); | |
225 | s += i; | |
226 | ||
227 | if(!(s = memmem(s, 0x1000, "PCG-", sizeof "PCG-" - 1))) return 0; | |
228 | ||
229 | if((i = txt_len(s))) { | |
230 | st->model = canon_str(s, i); | |
231 | } | |
232 | s += i; | |
233 | ||
234 | ADD2LOG(" vaio: %s\n", st->model); | |
235 | ||
236 | for(i = 0; i < 0x1000; i++) { | |
237 | if(is_decimal(s[i]) && txt_len(s + i) >= 10 && decimal_len(s + i) >= 5) { | |
238 | st->serial = canon_str(s + i, txt_len(s + i)); | |
239 | break; | |
240 | } | |
241 | } | |
242 | ||
243 | if(st->model) { | |
244 | s0 = strrchr(st->model, '('); | |
245 | s1 = strrchr(st->model, ')'); | |
246 | ||
247 | if(s0 && s1 && s1 - s0 >= 3 && s1[1] == 0) { | |
248 | st->lang = canon_str(s0 + 1, s1 - s0 - 1); | |
249 | for(s = st->lang; *s; s++) { | |
250 | if(*s >= 'A' && *s <= 'Z') *s += 'a' - 'A'; | |
251 | } | |
252 | if(!strcmp(st->lang, "uc")) strcpy(st->lang, "en"); | |
253 | *s0 = 0; /* cut the model entry */ | |
254 | } | |
255 | } | |
256 | ||
257 | return st->model ? 1 : 0; | |
258 | } | |
259 | #endif /* __i386__ || __x86_64__ */ | |
260 |