]>
Commit | Line | Data |
---|---|---|
c7de829c WD |
1 | #include <unistd.h> |
2 | #include <fcntl.h> | |
3 | #include <stdio.h> | |
4 | #include <sys/mman.h> | |
5 | #include <sys/types.h> | |
6 | #include <string.h> | |
7 | #include <stdlib.h> | |
8 | #include <signal.h> | |
9 | #include <sys/stat.h> | |
10 | #include <getopt.h> | |
11 | #if defined(__alpha__) || defined (__ia64__) | |
12 | #include <sys/io.h> | |
13 | #elif defined(HAVE_SYS_PERM) | |
14 | #include <sys/perm.h> | |
15 | #endif | |
16 | #include "debug.h" | |
17 | #include "v86bios.h" | |
18 | #include "pci.h" | |
19 | #include "AsmMacros.h" | |
20 | ||
21 | #define SIZE 0x100000 | |
22 | #define VRAM_START 0xA0000 | |
23 | #define VRAM_SIZE 0x1FFFF | |
24 | #define V_BIOS_SIZE 0x1FFFF | |
25 | #define BIOS_START 0x7C00 /* default BIOS entry */ | |
26 | #define BIOS_MEM 0x600 | |
27 | ||
28 | CARD8 code[] = { 0xcd, 0x10, 0xf4 }; | |
29 | struct config Config; | |
30 | ||
31 | static int map(void); | |
32 | static void unmap(void); | |
33 | static void runBIOS(int argc, char **argv); | |
34 | static int map_vram(void); | |
35 | static void unmap_vram(void); | |
36 | static int copy_vbios(memType base); | |
37 | static int copy_sys_bios(void); | |
38 | static CARD32 setup_int_vect(void); | |
39 | static void update_bios_vars(void); | |
40 | static int chksum(CARD8 *start); | |
41 | static void setup_bios_regs(i86biosRegsPtr regs, int argc, char **argv); | |
42 | static void print_regs(i86biosRegsPtr regs); | |
43 | void dprint(unsigned long start, unsigned long size); | |
44 | ||
45 | void loadCodeToMem(unsigned char *ptr, CARD8 *code); | |
46 | ||
47 | static int vram_mapped = 0; | |
48 | static char* bios_var; | |
49 | ||
50 | ||
51 | int | |
52 | main(int argc,char **argv) | |
53 | { | |
54 | CARD32 vbios_base; | |
55 | ||
56 | Config.PrintPort = PRINT_PORT; | |
57 | Config.IoStatistics = IO_STATISTICS; | |
58 | Config.PrintIrq = PRINT_IRQ; | |
59 | Config.PrintPci = PRINT_PCI; | |
8bde7f77 WD |
60 | Config.ShowAllDev = SHOW_ALL_DEV; |
61 | Config.PrintIp = PRINT_IP; | |
62 | Config.SaveBios = SAVE_BIOS; | |
63 | Config.Trace = TRACE; | |
64 | Config.ConfigActiveOnly = CONFIG_ACTIVE_ONLY; | |
c7de829c | 65 | Config.ConfigActiveDevice = CONFIG_ACTIVE_DEVICE; |
8bde7f77 WD |
66 | Config.MapSysBios = MAP_SYS_BIOS; |
67 | Config.Resort = RESORT; | |
68 | Config.FixRom = FIX_ROM; | |
69 | Config.NoConsole = NO_CONSOLE; | |
c7de829c | 70 | Config.Verbose = VERBOSE; |
8bde7f77 | 71 | |
c7de829c WD |
72 | if (!map()) |
73 | exit(1); | |
74 | if (!copy_sys_bios()) | |
75 | exit(1); | |
76 | if (!(vbios_base = setup_int_vect())) | |
77 | exit(1); | |
78 | if (!map_vram()) | |
79 | exit(1); | |
80 | if (!copy_vbios(vbios_base)) | |
81 | exit(1); | |
8bde7f77 | 82 | |
c7de829c WD |
83 | iopl(3); |
84 | setup_io(); | |
85 | runBIOS(argc,argv); | |
86 | update_bios_vars(); | |
87 | unmap_vram(); | |
88 | iopl(0); | |
89 | unmap(); | |
90 | printf("done !\n"); | |
91 | exit (1); | |
92 | } | |
93 | ||
8bde7f77 | 94 | int |
c7de829c WD |
95 | map(void) |
96 | { | |
97 | void* mem; | |
98 | ||
99 | mem = mmap(0, (size_t)SIZE, | |
8bde7f77 WD |
100 | PROT_EXEC | PROT_READ | PROT_WRITE, |
101 | MAP_FIXED | MAP_PRIVATE | MAP_ANON, | |
102 | -1, 0 ); | |
c7de829c | 103 | if (mem != 0) { |
8bde7f77 WD |
104 | perror("anonymous map"); |
105 | return (0); | |
c7de829c WD |
106 | } |
107 | memset(mem,0,SIZE); | |
108 | ||
109 | loadCodeToMem((unsigned char *) BIOS_START, code); | |
110 | return (1); | |
111 | } | |
112 | ||
113 | static int | |
114 | copy_sys_bios(void) | |
115 | { | |
116 | #define SYS_BIOS 0xF0000 | |
117 | int mem_fd; | |
118 | ||
119 | if ((mem_fd = open(MEM_FILE,O_RDONLY))<0) { | |
8bde7f77 WD |
120 | perror("opening memory"); |
121 | return (0); | |
c7de829c | 122 | } |
8bde7f77 WD |
123 | |
124 | if (lseek(mem_fd,(off_t) SYS_BIOS,SEEK_SET) != (off_t) SYS_BIOS) | |
125 | goto Error; | |
126 | if (read(mem_fd, (char *)SYS_BIOS, (size_t) 0xFFFF) != (size_t) 0xFFFF) | |
127 | goto Error; | |
c7de829c WD |
128 | |
129 | close(mem_fd); | |
130 | return (1); | |
131 | ||
132 | Error: | |
133 | perror("sys_bios"); | |
134 | close(mem_fd); | |
135 | return (0); | |
136 | } | |
137 | ||
138 | static int | |
139 | map_vram(void) | |
140 | { | |
141 | int mem_fd; | |
142 | ||
143 | #ifdef __ia64__ | |
8bde7f77 | 144 | if ((mem_fd = open(MEM_FILE,O_RDWR | O_SYNC))<0) |
c7de829c | 145 | #else |
8bde7f77 | 146 | if ((mem_fd = open(MEM_FILE,O_RDWR))<0) |
c7de829c WD |
147 | #endif |
148 | { | |
8bde7f77 WD |
149 | perror("opening memory"); |
150 | return 0; | |
c7de829c WD |
151 | } |
152 | ||
153 | #ifndef __alpha__ | |
154 | if (mmap((void *) VRAM_START, (size_t) VRAM_SIZE, | |
8bde7f77 WD |
155 | PROT_EXEC | PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, |
156 | mem_fd, VRAM_START) == (void *) -1) | |
c7de829c | 157 | #else |
8bde7f77 WD |
158 | if (!_bus_base()) sparse_shift = 7; /* Uh, oh, JENSEN... */ |
159 | if (!_bus_base_sparse()) sparse_shift = 0; | |
160 | if ((vram_map = mmap(0,(size_t) (VRAM_SIZE << sparse_shift), | |
161 | PROT_READ | PROT_WRITE, | |
162 | MAP_SHARED, | |
163 | mem_fd, (VRAM_START << sparse_shift) | |
164 | | _bus_base_sparse())) == (void *) -1) | |
c7de829c WD |
165 | #endif |
166 | { | |
8bde7f77 WD |
167 | perror("mmap error in map_hardware_ram"); |
168 | close(mem_fd); | |
169 | return (0); | |
170 | } | |
c7de829c WD |
171 | vram_mapped = 1; |
172 | close(mem_fd); | |
173 | return (1); | |
174 | } | |
175 | ||
176 | static int | |
177 | copy_vbios(memType v_base) | |
178 | { | |
179 | int mem_fd; | |
180 | unsigned char *tmp; | |
181 | int size; | |
182 | ||
183 | if ((mem_fd = open(MEM_FILE,O_RDONLY))<0) { | |
8bde7f77 WD |
184 | perror("opening memory"); |
185 | return (0); | |
c7de829c WD |
186 | } |
187 | ||
8bde7f77 WD |
188 | if (lseek(mem_fd,(off_t) v_base, SEEK_SET) != (off_t) v_base) { |
189 | fprintf(stderr,"Cannot lseek\n"); | |
190 | goto Error; | |
c7de829c WD |
191 | } |
192 | tmp = (unsigned char *)malloc(3); | |
193 | if (read(mem_fd, (char *)tmp, (size_t) 3) != (size_t) 3) { | |
8bde7f77 WD |
194 | fprintf(stderr,"Cannot read\n"); |
195 | goto Error; | |
c7de829c | 196 | } |
8bde7f77 WD |
197 | if (lseek(mem_fd,(off_t) v_base,SEEK_SET) != (off_t) v_base) |
198 | goto Error; | |
c7de829c WD |
199 | |
200 | if (*tmp != 0x55 || *(tmp+1) != 0xAA ) { | |
8bde7f77 WD |
201 | fprintf(stderr,"No bios found at: 0x%lx\n",v_base); |
202 | goto Error; | |
c7de829c WD |
203 | } |
204 | #ifdef DEBUG | |
8bde7f77 | 205 | dprint((unsigned long)tmp,0x100); |
c7de829c WD |
206 | #endif |
207 | size = *(tmp+2) * 512; | |
208 | ||
209 | if (read(mem_fd, (char *)v_base, (size_t) size) != (size_t) size) { | |
8bde7f77 WD |
210 | fprintf(stderr,"Cannot read\n"); |
211 | goto Error; | |
c7de829c WD |
212 | } |
213 | free(tmp); | |
214 | close(mem_fd); | |
215 | if (!chksum((CARD8*)v_base)) | |
8bde7f77 | 216 | return (0); |
c7de829c WD |
217 | |
218 | return (1); | |
219 | ||
220 | Error: | |
221 | perror("v_bios"); | |
222 | close(mem_fd); | |
223 | return (0); | |
224 | } | |
225 | ||
226 | static void | |
227 | unmap(void) | |
228 | { | |
229 | munmap(0,SIZE); | |
230 | } | |
231 | ||
232 | static void | |
233 | unmap_vram(void) | |
234 | { | |
235 | if (!vram_mapped) return; | |
8bde7f77 | 236 | |
c7de829c WD |
237 | munmap((void*)VRAM_START,VRAM_SIZE); |
238 | vram_mapped = 0; | |
239 | } | |
240 | ||
241 | static void | |
242 | runBIOS(int argc, char ** argv) | |
243 | { | |
244 | i86biosRegs bRegs; | |
245 | #ifdef V86BIOS_DEBUG | |
246 | printf("starting BIOS\n"); | |
247 | #endif | |
248 | setup_bios_regs(&bRegs, argc, argv); | |
249 | do_x86(BIOS_START,&bRegs); | |
250 | print_regs(&bRegs); | |
251 | #ifdef V86BIOS_DEBUG | |
252 | printf("done\n"); | |
253 | #endif | |
254 | } | |
255 | ||
256 | static CARD32 | |
257 | setup_int_vect(void) | |
258 | { | |
259 | int mem_fd; | |
260 | CARD32 vbase; | |
261 | void *map; | |
8bde7f77 | 262 | |
c7de829c WD |
263 | if ((mem_fd = open(MEM_FILE,O_RDONLY))<0) { |
264 | perror("opening memory"); | |
265 | return (0); | |
266 | } | |
8bde7f77 | 267 | |
c7de829c | 268 | if ((map = mmap((void *) 0, (size_t) 0x2000, |
8bde7f77 WD |
269 | PROT_EXEC | PROT_READ | PROT_WRITE, MAP_SHARED, |
270 | mem_fd, 0)) == (void *)-1) { | |
c7de829c WD |
271 | perror("mmap error in map_hardware_ram"); |
272 | close(mem_fd); | |
273 | return (0); | |
274 | } | |
275 | ||
276 | close(mem_fd); | |
277 | memcpy(0,map,BIOS_MEM); | |
278 | munmap(map,0x2000); | |
279 | /* | |
280 | * create a backup copy of the bios variables to write back the | |
281 | * modified values | |
282 | */ | |
283 | bios_var = (char *)malloc(BIOS_MEM); | |
284 | memcpy(bios_var,0,BIOS_MEM); | |
8bde7f77 | 285 | |
c7de829c WD |
286 | vbase = (*((CARD16*)(0x10 << 2) + 1)) << 4; |
287 | fprintf(stderr,"vbase: 0x%x\n",vbase); | |
288 | return vbase; | |
289 | } | |
290 | ||
291 | static void | |
292 | update_bios_vars(void) | |
293 | { | |
294 | int mem_fd; | |
295 | void *map; | |
296 | memType i; | |
8bde7f77 | 297 | |
c7de829c | 298 | #ifdef __ia64__ |
8bde7f77 | 299 | if ((mem_fd = open(MEM_FILE,O_RDWR | O_SYNC))<0) |
c7de829c | 300 | #else |
8bde7f77 | 301 | if ((mem_fd = open(MEM_FILE,O_RDWR))<0) |
c7de829c WD |
302 | #endif |
303 | { | |
8bde7f77 WD |
304 | perror("opening memory"); |
305 | return; | |
c7de829c | 306 | } |
8bde7f77 | 307 | |
c7de829c | 308 | if ((map = mmap((void *) 0, (size_t) 0x2000, |
8bde7f77 WD |
309 | PROT_EXEC | PROT_READ | PROT_WRITE, MAP_SHARED, |
310 | mem_fd, 0)) == (void *)-1) { | |
c7de829c WD |
311 | perror("mmap error in map_hardware_ram"); |
312 | close(mem_fd); | |
313 | return; | |
314 | } | |
315 | ||
316 | for (i = 0; i < BIOS_MEM; i++) { | |
8bde7f77 WD |
317 | if (bios_var[i] != *(CARD8*)i) |
318 | *((CARD8*)map + i) = *(CARD8*)i; | |
c7de829c WD |
319 | } |
320 | ||
321 | munmap(map,0x2000); | |
322 | close(mem_fd); | |
323 | } | |
324 | ||
325 | ||
326 | static void | |
327 | setup_bios_regs(i86biosRegsPtr regs, int argc, char **argv) | |
328 | { | |
329 | int c; | |
330 | ||
331 | regs->ax = 0; | |
332 | regs->bx = 0; | |
333 | regs->cx = 0; | |
334 | regs->dx = 0; | |
335 | regs->es = 0; | |
336 | regs->di = 0; | |
337 | opterr = 0; | |
338 | while ((c = getopt(argc,argv,"a:b:c:d:e:i:")) != EOF) { | |
339 | switch (c) { | |
340 | case 'a': | |
8bde7f77 WD |
341 | regs->ax = strtol(optarg,NULL,0); |
342 | break; | |
c7de829c | 343 | case 'b': |
8bde7f77 WD |
344 | regs->bx = strtol(optarg,NULL,0); |
345 | break; | |
c7de829c | 346 | case 'c': |
8bde7f77 WD |
347 | regs->cx = strtol(optarg,NULL,0); |
348 | break; | |
c7de829c | 349 | case 'd': |
8bde7f77 WD |
350 | regs->dx = strtol(optarg,NULL,0); |
351 | break; | |
c7de829c | 352 | case 'e': |
8bde7f77 WD |
353 | regs->es = strtol(optarg,NULL,0); |
354 | break; | |
c7de829c | 355 | case 'i': |
8bde7f77 WD |
356 | regs->di = strtol(optarg,NULL,0); |
357 | break; | |
c7de829c WD |
358 | } |
359 | } | |
360 | } | |
361 | ||
362 | ||
363 | static int | |
364 | chksum(CARD8 *start) | |
365 | { | |
366 | CARD16 size; | |
367 | CARD8 val = 0; | |
368 | int i; | |
369 | ||
8bde7f77 | 370 | size = *(start+2) * 512; |
c7de829c WD |
371 | for (i = 0; i<size; i++) |
372 | val += *(start + i); | |
8bde7f77 | 373 | |
c7de829c WD |
374 | if (!val) |
375 | return 1; | |
376 | ||
377 | fprintf(stderr,"BIOS cksum wrong!\n"); | |
378 | return 0; | |
379 | } | |
380 | ||
381 | static void | |
382 | print_regs(i86biosRegsPtr regs) | |
383 | { | |
384 | printf("ax=%x bx=%x cx=%x dx=%x es=%x di=%x\n",(CARD16)regs->ax, | |
385 | (CARD16)regs->bx,(CARD16)regs->cx,(CARD16)regs->dx, | |
386 | (CARD16)regs->es,(CARD16)regs->di); | |
387 | } | |
388 | ||
389 | void | |
390 | loadCodeToMem(unsigned char *ptr, CARD8 code[]) | |
391 | { | |
392 | int i; | |
393 | CARD8 val; | |
8bde7f77 | 394 | |
c7de829c | 395 | for ( i=0;;i++) { |
8bde7f77 WD |
396 | val = code[i]; |
397 | *ptr++ = val; | |
398 | if (val == 0xf4) break; | |
c7de829c WD |
399 | } |
400 | return; | |
401 | } | |
402 | ||
8bde7f77 | 403 | void |
c7de829c WD |
404 | dprint(unsigned long start, unsigned long size) |
405 | { | |
406 | int i,j; | |
407 | char *c = (char *)start; | |
408 | ||
409 | for (j = 0; j < (size >> 4); j++) { | |
8bde7f77 WD |
410 | printf ("\n0x%lx: ",(unsigned long)c); |
411 | for (i = 0; i<16; i++) | |
412 | printf("%x ",(unsigned char) (*(c++))); | |
c7de829c WD |
413 | } |
414 | printf("\n"); | |
415 | } |