]> git.karo-electronics.de Git - karo-tx-uboot.git/blob - board/MAI/bios_emulator/scitech/src/v86bios/main.c
* Code cleanup:
[karo-tx-uboot.git] / board / MAI / bios_emulator / scitech / src / v86bios / main.c
1 /*
2  * Copyright 1999 Egbert Eich
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and its
5  * documentation for any purpose is hereby granted without fee, provided that
6  * the above copyright notice appear in all copies and that both that
7  * copyright notice and this permission notice appear in supporting
8  * documentation, and that the name of the authors not be used in
9  * advertising or publicity pertaining to distribution of the software without
10  * specific, written prior permission.  The authors makes no representations
11  * about the suitability of this software for any purpose.  It is provided
12  * "as is" without express or implied warranty.
13  *
14  * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16  * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20  * PERFORMANCE OF THIS SOFTWARE.
21  */
22 #define DELETE
23 #include <unistd.h>
24 #include <fcntl.h>
25 #include <stdio.h>
26 #include <sys/mman.h>
27 #include <sys/types.h>
28 #include <string.h>
29 #include <stdlib.h>
30 #include <signal.h>
31 #include <sys/stat.h>
32 #if defined(__alpha__) || defined (__ia64__)
33 #include <sys/io.h>
34 #elif defined(HAVE_SYS_PERM)
35 #include <sys/perm.h>
36 #endif
37 #include "debug.h"
38 #include "v86bios.h"
39 #include "pci.h"
40 #include "AsmMacros.h"
41
42 #define SIZE 0x100000
43 #define VRAM_START 0xA0000
44 #define VRAM_SIZE 0x1FFFF
45 #define V_BIOS_SIZE 0x1FFFF
46 #define BIOS_START 0x7C00            /* default BIOS entry */
47
48 /*CARD8 code[] = { 0xb8 , 0xf0 , 0xf0, 0xf4 }; */
49 #define VB_X(x) (V_BIOS >> x) & 0xFF
50 CARD8 code[] = { 0x9a, 0x03, 0x00, 0x00, VB_X(12), 0xf4 };
51 /*CARD8 code[] = { 0x9a, 0x03, 0x00, 0x00, VB_X(12), 0xb8, 0x03, 0x00, */
52 /*0xcd, 0x10, 0xf4 }; */
53 /*CARD8 code[] = {  0xb8 , 0xf0 , 0xf0 ,0xf4 }; */
54
55 static void sig_handler(int);
56 static int map(void);
57 static void unmap(void);
58 static void bootBIOS(CARD16 ax);
59 static int map_vram(void);
60 static void unmap_vram(void);
61 static int copy_vbios(void);
62 static int copy_sys_bios(void);
63 static void save_bios_to_file(void);
64 static int setup_system_bios(void);
65 static void setup_int_vect(void);
66 static int chksum(CARD8 *start);
67 static void setup_bios_regs(i86biosRegsPtr regs, CARD32 ax);
68
69 void loadCodeToMem(unsigned char *ptr, CARD8 *code);
70 void dprint(unsigned long start, unsigned long size);
71
72 static int vram_mapped = 0;
73 static CARD8 save_msr;
74 static CARD8 save_pos102;
75 static CARD8 save_vse;
76 static CARD8 save_46e8;
77 console Console;
78 struct config Config;
79
80
81 int
82 main(void)
83 {
84     int Active_is_Pci = 0;
85 #ifdef DELETE
86     Config.PrintPort = PRINT_PORT;
87     Config.IoStatistics = IO_STATISTICS;
88     Config.PrintIrq = PRINT_IRQ;
89     Config.PrintPci = PRINT_PCI;
90     Config.ShowAllDev = SHOW_ALL_DEV;
91     Config.PrintIp = PRINT_IP;
92     Config.SaveBios = SAVE_BIOS;
93     Config.Trace = TRACE;
94     Config.ConfigActiveOnly = CONFIG_ACTIVE_ONLY;
95     Config.ConfigActiveDevice = CONFIG_ACTIVE_DEVICE;
96     Config.MapSysBios = MAP_SYS_BIOS;
97     Config.Resort = RESORT;
98     Config.FixRom = FIX_ROM;
99     Config.NoConsole = NO_CONSOLE;
100     Config.Verbose = VERBOSE;
101
102     if (!map())
103         exit(1);
104
105     if (!setup_system_bios())
106         exit(1);
107
108     iopl(3);
109     setup_io();
110
111     scan_pci();
112     if (!CurrentPci && !Config.ConfigActiveDevice && !Config.ConfigActiveOnly)
113         exit (1);
114 #endif
115     Console = open_console();
116
117     if (Config.ConfigActiveOnly) {
118         CARD16 ax;
119         int activePci = 0;
120         int error = 0;
121
122         while (CurrentPci) {
123             if (CurrentPci->active) {
124                 activePci = 1;
125                             if (!(mapPciRom(NULL) && chksum((CARD8*)V_BIOS)))
126                                 error = 1;
127                             break;
128             }
129             CurrentPci = CurrentPci->next;
130         }
131         ax = ((CARD16)(CurrentPci->bus) << 8)
132             | (CurrentPci->dev << 3) | (CurrentPci->func & 0x7);
133         P_printf("ax: 0x%x\n",ax);
134         setup_int_vect();
135         if (!error && (activePci || copy_vbios())) {
136
137             if (Config.SaveBios) save_bios_to_file();
138             if  (map_vram()) {
139                 printf("initializing ISA\n");
140                             bootBIOS(0);
141             }
142         }
143         unmap_vram();
144         sleep(1);
145     } else {
146         /* disable primary card */
147         save_msr = inb(0x3CC);
148         save_vse = inb(0x3C3);
149         save_46e8 = inb(0x46e8);
150         save_pos102 = inb(0x102);
151
152         signal(2,sig_handler);
153         signal(11,sig_handler);
154
155         outb(0x3C2,~(CARD8)0x03 & save_msr);
156         outb(0x3C3,~(CARD8)0x01 & save_vse);
157         outb(0x46e8, ~(CARD8)0x08 & save_46e8);
158         outb(0x102, ~(CARD8)0x01 & save_pos102);
159
160         pciVideoDisable();
161
162         while (CurrentPci) {
163             CARD16 ax;
164
165             if (CurrentPci->active) {
166                 Active_is_Pci = 1;
167                 if (!Config.ConfigActiveDevice) {
168                     CurrentPci = CurrentPci->next;
169                     continue;
170                 }
171             }
172
173             EnableCurrent();
174
175             if (CurrentPci->active) {
176                 outb(0x102, save_pos102);
177                 outb(0x46e8, save_46e8);
178                 outb(0x3C3, save_vse);
179                 outb(0x3C2, save_msr);
180             }
181
182             /* clear interrupt vectors */
183             setup_int_vect();
184
185             ax = ((CARD16)(CurrentPci->bus) << 8)
186                 | (CurrentPci->dev << 3) | (CurrentPci->func & 0x7);
187             P_printf("ax: 0x%x\n",ax);
188
189             if (!((mapPciRom(NULL) && chksum((CARD8*)V_BIOS))
190                   || (CurrentPci->active && copy_vbios()))) {
191                 CurrentPci = CurrentPci->next;
192                 continue;
193             }
194             if (!map_vram()) {
195                 CurrentPci = CurrentPci->next;
196                 continue;
197             }
198             if (Config.SaveBios) save_bios_to_file();
199             printf("initializing PCI bus: %i dev: %i func: %i\n",CurrentPci->bus,
200                    CurrentPci->dev,CurrentPci->func);
201             bootBIOS(ax);
202             unmap_vram();
203
204             CurrentPci = CurrentPci->next;
205         }
206
207         /* We have an ISA device - configure if requested */
208         if (!Active_is_Pci && Config.ConfigActiveDevice) {
209             pciVideoDisable();
210
211             outb(0x102, save_pos102);
212             outb(0x46e8, save_46e8);
213             outb(0x3C3, save_vse);
214             outb(0x3C2, save_msr);
215
216             setup_int_vect();
217             if (copy_vbios()) {
218
219                 if (Config.SaveBios) save_bios_to_file();
220                 if  (map_vram()) {
221                     printf("initializing ISA\n");
222                     bootBIOS(0);
223                 }
224             }
225
226             unmap_vram();
227             sleep(1);
228         }
229
230         pciVideoRestore();
231
232         outb(0x102, save_pos102);
233         outb(0x46e8, save_46e8);
234         outb(0x3C3, save_vse);
235         outb(0x3C2, save_msr);
236     }
237
238     close_console(Console);
239 #ifdef DELETE
240     iopl(0);
241     unmap();
242
243     printf("done !\n");
244 #endif
245     if (Config.IoStatistics)
246         io_statistics();
247 #ifdef DELETE
248     exit(0);
249 #endif
250 }
251
252 int
253 map(void)
254 {
255     void* mem;
256
257     mem = mmap(0, (size_t)SIZE,
258                PROT_EXEC | PROT_READ | PROT_WRITE,
259                MAP_FIXED | MAP_PRIVATE | MAP_ANON,
260                -1, 0 );
261     if (mem != 0) {
262         perror("anonymous map");
263         return (0);
264     }
265     memset(mem,0,SIZE);
266
267     loadCodeToMem((unsigned char *) BIOS_START, code);
268     return (1);
269 }
270
271 static void
272 unmap(void)
273 {
274     munmap(0,SIZE);
275 }
276
277 static void
278 bootBIOS(CARD16 ax)
279 {
280     i86biosRegs bRegs;
281 #ifdef V86BIOS_DEBUG
282     printf("starting BIOS\n");
283 #endif
284     setup_bios_regs(&bRegs, ax);
285     do_x86(BIOS_START,&bRegs);
286 #ifdef V86BIOS_DEBUG
287     printf("done\n");
288 #endif
289 }
290
291 static int
292 map_vram(void)
293 {
294     int mem_fd;
295
296 #ifdef __ia64__
297     if ((mem_fd = open(MEM_FILE,O_RDWR | O_SYNC))<0)
298 #else
299     if ((mem_fd = open(MEM_FILE,O_RDWR))<0)
300 #endif
301       {
302         perror("opening memory");
303         return 0;
304     }
305
306 #ifndef __alpha__
307     if (mmap((void *) VRAM_START, (size_t) VRAM_SIZE,
308                      PROT_EXEC | PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED,
309                      mem_fd, VRAM_START) == (void *) -1)
310 #else
311          if (!_bus_base()) sparse_shift = 7; /* Uh, oh, JENSEN... */
312          if (!_bus_base_sparse()) sparse_shift = 0;
313          if ((vram_map = mmap(0,(size_t) (VRAM_SIZE << sparse_shift),
314                                                  PROT_READ | PROT_WRITE,
315                                                  MAP_SHARED,
316                                                  mem_fd, (VRAM_START << sparse_shift)
317                                                  | _bus_base_sparse())) == (void *) -1)
318 #endif
319       {
320         perror("mmap error in map_hardware_ram");
321             close(mem_fd);
322             return (0);
323         }
324     vram_mapped = 1;
325     close(mem_fd);
326     return (1);
327 }
328
329 static void
330 unmap_vram(void)
331 {
332     if (!vram_mapped) return;
333
334     munmap((void*)VRAM_START,VRAM_SIZE);
335     vram_mapped = 0;
336 }
337
338 static int
339 copy_vbios(void)
340 {
341     int mem_fd;
342     unsigned char *tmp;
343     int size;
344
345     if ((mem_fd = open(MEM_FILE,O_RDONLY))<0) {
346         perror("opening memory");
347         return (0);
348     }
349
350     if (lseek(mem_fd,(off_t) V_BIOS, SEEK_SET) != (off_t) V_BIOS) {
351           fprintf(stderr,"Cannot lseek\n");
352           goto Error;
353       }
354     tmp = (unsigned char *)malloc(3);
355     if (read(mem_fd, (char *)tmp, (size_t) 3) != (size_t) 3) {
356             fprintf(stderr,"Cannot read\n");
357         goto Error;
358     }
359     if (lseek(mem_fd,(off_t) V_BIOS,SEEK_SET) != (off_t) V_BIOS)
360         goto Error;
361
362     if (*tmp != 0x55 || *(tmp+1) != 0xAA ) {
363 #ifdef DEBUG
364         dprint((unsigned long)tmp,0x100);
365 #endif
366         fprintf(stderr,"No bios found at: 0x%x\n",V_BIOS);
367         goto Error;
368     }
369     size = *(tmp+2) * 512;
370
371     if (read(mem_fd, (char *)V_BIOS, (size_t) size) != (size_t) size) {
372             fprintf(stderr,"Cannot read\n");
373         goto Error;
374     }
375     free(tmp);
376     close(mem_fd);
377     if (!chksum((CARD8)V_BIOS))
378         return (0);
379
380     return (1);
381
382 Error:
383     perror("v_bios");
384     close(mem_fd);
385     return (0);
386 }
387
388 static int
389 copy_sys_bios(void)
390 {
391 #define SYS_BIOS 0xF0000
392     int mem_fd;
393
394     if ((mem_fd = open(MEM_FILE,O_RDONLY))<0) {
395         perror("opening memory");
396         return (0);
397     }
398
399     if (lseek(mem_fd,(off_t) SYS_BIOS,SEEK_SET) != (off_t) SYS_BIOS)
400         goto Error;
401     if (read(mem_fd, (char *)SYS_BIOS, (size_t) 0xFFFF) != (size_t) 0xFFFF)
402         goto Error;
403
404     close(mem_fd);
405     return (1);
406
407 Error:
408     perror("sys_bios");
409     close(mem_fd);
410     return (0);
411 }
412
413 void
414 loadCodeToMem(unsigned char *ptr, CARD8 code[])
415 {
416     int i;
417     CARD8 val;
418
419     for ( i=0;;i++) {
420         val = code[i];
421         *ptr++ = val;
422         if (val == 0xf4) break;
423     }
424     return;
425 }
426
427 void
428 dprint(unsigned long start, unsigned long size)
429 {
430     int i,j;
431     char *c = (char *)start;
432
433     for (j = 0; j < (size >> 4); j++) {
434     char *d = c;
435     printf("\n0x%lx:  ",(unsigned long)c);
436     for (i = 0; i<16; i++)
437         printf("%2.2x ",(unsigned char) (*(c++)));
438     c = d;
439     for (i = 0; i<16; i++) {
440         printf("%c",((((CARD8)(*c)) > 32) && (((CARD8)(*c)) < 128)) ?
441            (unsigned char) (*(c)): '.');
442         c++;
443     }
444     }
445     printf("\n");
446 }
447
448 static void
449 save_bios_to_file(void)
450 {
451     static int num = 0;
452     int size, count;
453     char file_name[256];
454     int fd;
455
456     sprintf(file_name,"bios_%i.fil",num);
457     if ((fd =  open(file_name,O_WRONLY | O_CREAT | O_TRUNC,00644)) == -1)
458         return;
459     size = (*(unsigned char*)(V_BIOS + 2)) * 512;
460 #ifdef V86BIOS_DEBUG
461     dprint(V_BIOS,20);
462 #endif
463     if ((count = write(fd,(void *)(V_BIOS),size)) != size)
464         fprintf(stderr,"only saved %i of %i bytes\n",size,count);
465     num++;
466 }
467
468 static void
469 sig_handler(int unused)
470 {
471     fflush(stdout);
472     fflush(stderr);
473
474     /* put system back in a save state */
475     unmap_vram();
476     pciVideoRestore();
477     outb(0x102, save_pos102);
478     outb(0x46e8, save_46e8);
479     outb(0x3C3, save_vse);
480     outb(0x3C2, save_msr);
481
482     close_console(Console);
483     iopl(0);
484     unmap();
485
486     exit(1);
487 }
488
489 /*
490  * For initialization we just pass ax to the BIOS.
491  * PCI BIOSes need this. All other register are set 0.
492  */
493 static void setup_bios_regs(i86biosRegsPtr regs, CARD32 ax)
494 {
495     regs->ax = ax;
496     regs->bx = 0;
497     regs->cx = 0;
498     regs->dx = 0;
499     regs->es = 0;
500     regs->di = 0;
501 }
502
503 /*
504  * here we are really paranoid about faking a "real"
505  * BIOS. Most of this information was pulled from
506  * dosem.
507  */
508 static void
509 setup_int_vect(void)
510 {
511     const CARD16 cs = 0x0000;
512     const CARD16 ip = 0x0;
513     int i;
514
515     /* let the int vects point to the SYS_BIOS seg */
516     for (i=0; i<0x80; i++) {
517         ((CARD16*)0)[i<<1] = ip;
518         ((CARD16*)0)[(i<<1)+1] = cs;
519     }
520     /* video interrupts default location */
521     ((CARD16*)0)[(0x42<<1)+1] = 0xf000;
522     ((CARD16*)0)[0x42<<1] = 0xf065;
523     ((CARD16*)0)[(0x10<<1)+1] = 0xf000;
524     ((CARD16*)0)[0x10<<1] = 0xf065;
525     /* video param table default location (int 1d) */
526     ((CARD16*)0)[(0x1d<<1)+1] = 0xf000;
527     ((CARD16*)0)[0x1d<<1] = 0xf0A4;
528     /* font tables default location (int 1F) */
529     ((CARD16*)0)[(0x1f<<1)+1] = 0xf000;
530     ((CARD16*)0)[0x1f<<1] = 0xfa6e;
531
532     /* int 11 default location */
533     ((CARD16*)0)[(0x11<1)+1] = 0xf000;
534     ((CARD16*)0)[0x11<<1] = 0xf84d;
535     /* int 12 default location */
536     ((CARD16*)0)[(0x12<<1)+1] = 0xf000;
537     ((CARD16*)0)[0x12<<1] = 0xf841;
538     /* int 15 default location */
539     ((CARD16*)0)[(0x15<<1)+1] = 0xf000;
540     ((CARD16*)0)[0x15<<1] = 0xf859;
541     /* int 1A default location */
542     ((CARD16*)0)[(0x1a<<1)+1] = 0xf000;
543     ((CARD16*)0)[0x1a<<1] = 0xff6e;
544     /* int 05 default location */
545     ((CARD16*)0)[(0x05<<1)+1] = 0xf000;
546     ((CARD16*)0)[0x05<<1] = 0xff54;
547     /* int 08 default location */
548     ((CARD16*)0)[(0x8<<1)+1] = 0xf000;
549     ((CARD16*)0)[0x8<<1] = 0xfea5;
550     /* int 13 default location (fdd) */
551     ((CARD16*)0)[(0x13<<1)+1] = 0xf000;
552     ((CARD16*)0)[0x13<<1] = 0xec59;
553     /* int 0E default location */
554     ((CARD16*)0)[(0xe<<1)+1] = 0xf000;
555     ((CARD16*)0)[0xe<<1] = 0xef57;
556     /* int 17 default location */
557     ((CARD16*)0)[(0x17<<1)+1] = 0xf000;
558     ((CARD16*)0)[0x17<<1] = 0xefd2;
559     /* fdd table default location (int 1e) */
560     ((CARD16*)0)[(0x1e<<1)+1] = 0xf000;
561     ((CARD16*)0)[0x1e<<1] = 0xefc7;
562 }
563
564 static int
565 setup_system_bios(void)
566 {
567     char *date = "06/01/99";
568     char *eisa_ident = "PCI/ISA";
569
570 #if MAP_SYS_BIOS
571     if (!copy_sys_bios()) return 0;
572     return 1;
573 #endif
574 /*    memset((void *)0xF0000,0xf4,0xfff7); */
575
576     /*
577      * we trap the "industry standard entry points" to the BIOS
578      * and all other locations by filling them with "hlt"
579      * TODO: implement hlt-handler for these
580      */
581     memset((void *)0xF0000,0xf4,0x10000);
582
583     /*
584      * TODO: we should copy the fdd table (0xfec59-0xfec5b)
585      * the video parameter table (0xf0ac-0xf0fb)
586      * and the font tables (0xfa6e-0xfe6d)
587      * from the original bios here
588      */
589
590     /* set bios date */
591     strcpy((char *)0xFFFF5,date);
592     /* set up eisa ident string */
593     strcpy((char *)0xFFFD9,eisa_ident);
594     /* write system model id for IBM-AT */
595     ((char *)0)[0xFFFFE] = 0xfc;
596
597     return 1;
598 }
599
600 static int
601 chksum(CARD8 *start)
602 {
603   CARD16 size;
604   CARD8 val = 0;
605   int i;
606
607   size = *(start+2) * 512;
608   for (i = 0; i<size; i++)
609     val += *(start + i);
610
611   if (!val)
612     return 1;
613
614     fprintf(stderr,"BIOS cksum wrong!\n");
615   return 0;
616 }