This commit was manufactured by cvs2svn to create tag
[opensuse:hwinfo.git] / src / int10 / i10_vbios.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 #include <unistd.h>
23 #include <fcntl.h>
24 #include <stdio.h>
25 #include <sys/mman.h>
26 #include <sys/types.h>
27 #include <string.h>
28 #include <stdlib.h>
29 #include <signal.h>
30 #include <sys/stat.h>
31 #if defined(__alpha__) || defined (__ia64__)
32 #include <sys/io.h>
33 //#elif defined(HAVE_SYS_PERM)
34 #else
35 #include <sys/perm.h>
36 #endif
37 #include "v86bios.h"
38 #include "pci.h"
39 #include "AsmMacros.h"
40 #include "vbios.h"
41
42 void log_err(char *format, ...) __attribute__ ((format (printf, 1, 2)));
43
44 #define SIZE 0x100000
45 #define VRAM_START 0xA0000
46 #define VRAM_SIZE 0x1FFFF
47 #define V_BIOS_SIZE 0x1FFFF
48 #define BIOS_START 0x7C00            /* default BIOS entry */
49
50 static CARD8 code[] = {  0xcd, 0x10 ,0xf4 };    /* int 0x10, hlt */
51 #if 0
52 static CARD8 code[] =
53 {
54   0xb8, 0xff, 0xff, 0x8e, 0xd8, 0xbe, 0x00, 0xff,
55   0x8a, 0x04, 0xf4, 0x00, 0x00, 0x00, 0x00, 0x00
56 };
57 #endif
58
59 static int map(void);
60 static void unmap(void);
61 static int map_vram(void);
62 static void unmap_vram(void);
63 static int copy_vbios(void);
64 #if MAP_SYS_BIOS
65 static int copy_sys_bios(void);
66 #endif
67 static int copy_bios_ram();
68 static int setup_system_bios(void);
69 static void setup_int_vect(void);
70 static int chksum(CARD8 *start);
71
72 void loadCodeToMem(unsigned char *ptr, CARD8 *code);
73
74 static int vram_mapped = 0;
75 static int int10inited = 0;
76
77 int
78 InitInt10()
79 {
80   if (geteuid())
81     return -1;
82   if (!map())
83     return -1;
84         
85   if (!setup_system_bios())
86     {
87       unmap();
88       return -1;
89     }
90   setup_io();
91 #if 1
92   iopl(3);
93   scan_pci();
94   for (; CurrentPci; CurrentPci = CurrentPci->next)
95     if (CurrentPci->active)
96       {
97 #if 0
98         if (!mapPciRom(NULL) || !chksum((CARD8*)V_BIOS))
99           {
100             iopl(0);
101             unmap();
102             return -1;
103           }
104 #endif
105         break;
106       }
107   iopl(0);
108 #endif
109   setup_int_vect();
110 #if 0
111   if (!CurrentPci && !copy_vbios())
112     {
113       unmap();
114       return -1;
115     }
116 #else
117   if (!copy_vbios())
118     {
119       unmap();
120       return -1;
121     }
122 #endif
123   if (!map_vram() || !copy_bios_ram())
124     {
125       unmap();
126       return -1;
127     }
128   int10inited = 1;
129   return 0;
130 }
131
132 void
133 FreeInt10()
134 {
135   if (!int10inited)
136     return;
137   unmap_vram();
138   unmap();
139   int10inited = 0;
140 }
141
142 int
143 CallInt10(int *ax, int *bx, int *cx, unsigned char *buf, int len)
144 {
145   i86biosRegs bRegs;
146
147   if (!int10inited)
148     return -1;
149   memset(&bRegs, 0, sizeof bRegs);
150   bRegs.ax = *ax;
151   bRegs.bx = *bx;
152   bRegs.cx = *cx;
153   bRegs.dx = 0;
154   bRegs.es = 0x7e0;
155   bRegs.di = 0x0;
156   if (buf)
157     memcpy((unsigned char *)0x7e00, buf, len);
158   iopl(3);
159   do_x86(BIOS_START,&bRegs);
160   iopl(0);
161   if (buf)
162     memcpy(buf, (unsigned char *)0x7e00, len);
163
164   *ax = bRegs.ax;
165   *bx = bRegs.bx;
166   *cx = bRegs.cx;
167
168   return bRegs.ax;
169 }
170
171 int  
172 map(void)
173 {
174         void* mem;
175
176         mem = mmap(0, (size_t)SIZE,
177                            PROT_EXEC | PROT_READ | PROT_WRITE,
178                            MAP_FIXED | MAP_PRIVATE | MAP_ANON,
179                            -1, 0 ); 
180         if (mem != 0) {
181                 perror("anonymous map");
182                 return (0);
183         }
184         memset(mem,0,SIZE);
185
186         loadCodeToMem((unsigned char *) BIOS_START, code);
187         return (1);
188 }
189
190 static void
191 unmap(void)
192 {
193         munmap(0,SIZE);
194 }
195
196 static int
197 map_vram(void)
198 {
199         int mem_fd;
200
201 #ifdef __ia64__
202         if ((mem_fd = open(MEM_FILE,O_RDWR | O_SYNC))<0) 
203 #else
204         if ((mem_fd = open(MEM_FILE,O_RDWR))<0) 
205 #endif
206           {
207                 perror("opening memory");
208                 return 0;
209         }
210
211 #ifndef __alpha__
212         if (mmap((void *) VRAM_START, (size_t) VRAM_SIZE,
213                                          PROT_EXEC | PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED,
214                                          mem_fd, VRAM_START) == (void *) -1) 
215 #else
216                  if (!_bus_base()) sparse_shift = 7; /* Uh, oh, JENSEN... */
217                  if (!_bus_base_sparse()) sparse_shift = 0;
218                  if ((vram_map = mmap(0,(size_t) (VRAM_SIZE << sparse_shift),
219                                                                                                  PROT_READ | PROT_WRITE,
220                                                                                                  MAP_SHARED,
221                                                                                                  mem_fd, (VRAM_START << sparse_shift)
222                                                                                                  | _bus_base_sparse())) == (void *) -1)
223 #endif
224           {
225             perror("mmap error in map_hardware_ram");
226                         close(mem_fd);
227                         return (0);
228                 }
229         vram_mapped = 1;
230         close(mem_fd);
231         return (1);
232 }
233
234 static void
235 unmap_vram(void)
236 {
237         if (!vram_mapped) return;
238         
239         munmap((void*)VRAM_START,VRAM_SIZE);
240         vram_mapped = 0;
241 }
242
243 static int
244 copy_vbios(void)
245 {
246         int mem_fd;
247         unsigned char *tmp;
248         int size;
249
250         if ((mem_fd = open(MEM_FILE,O_RDONLY))<0) {
251                 perror("opening memory");
252                 return (0);
253         }
254
255         if (lseek(mem_fd,(off_t) V_BIOS, SEEK_SET) != (off_t) V_BIOS) { 
256               fprintf(stderr,"Cannot lseek\n");
257               goto Error;
258           }
259         tmp = (unsigned char *)malloc(3);
260         if (read(mem_fd, (char *)tmp, (size_t) 3) != (size_t) 3) {
261                 fprintf(stderr,"Cannot read\n");
262                 goto Error;
263         }
264         if (lseek(mem_fd,(off_t) V_BIOS,SEEK_SET) != (off_t) V_BIOS) 
265             goto Error;
266
267         if (*tmp != 0x55 || *(tmp+1) != 0xAA ) {
268                 fprintf(stderr,"No bios found at: 0x%x\n",V_BIOS);
269                 goto Error;
270         }
271         size = *(tmp+2) * 512;
272
273         if (read(mem_fd, (char *)V_BIOS, (size_t) size) != (size_t) size) {
274                 fprintf(stderr,"Cannot read\n");
275                 goto Error;
276         }
277         free(tmp);
278         close(mem_fd);
279         if (!chksum((CARD8 *)V_BIOS))
280                 return (0);
281
282         return (1);
283
284 Error:
285         perror("v_bios");
286         close(mem_fd);
287         return (0);
288 }
289
290 #if MAP_SYS_BIOS
291 static int
292 copy_sys_bios(void)
293 {
294 #define SYS_BIOS 0xF0000
295         int mem_fd;
296
297         if ((mem_fd = open(MEM_FILE,O_RDONLY))<0) {
298                 perror("opening memory");
299                 return (0);
300         }
301   
302         if (lseek(mem_fd,(off_t) SYS_BIOS,SEEK_SET) != (off_t) SYS_BIOS) 
303                 goto Error;
304         if (read(mem_fd, (char *)SYS_BIOS, (size_t) 0xFFFF) != (size_t) 0xFFFF) 
305                 goto Error;
306
307         close(mem_fd);
308         return (1);
309
310 Error:
311         perror("sys_bios");
312         close(mem_fd);
313         return (0);
314 }
315 #endif
316
317
318 static int
319 copy_bios_ram(void)
320 {
321 #define BIOS_RAM 0
322         int mem_fd;
323
324         if ((mem_fd = open(MEM_FILE,O_RDONLY))<0) {
325                 perror("opening memory");
326                 return (0);
327         }
328   
329         if (lseek(mem_fd,(off_t) BIOS_RAM,SEEK_SET) != (off_t) BIOS_RAM) 
330                 goto Error;
331         if (read(mem_fd, (char *)BIOS_RAM, (size_t) 0x1000) != (size_t) 0x1000) 
332                 goto Error;
333
334         close(mem_fd);
335         return (1);
336
337 Error:
338         perror("bios_ram");
339         close(mem_fd);
340         return (0);
341 }
342
343 void
344 loadCodeToMem(unsigned char *ptr, CARD8 code[])
345 {
346         int i;
347         CARD8 val;
348         
349         for ( i=0;;i++) {
350                 val = code[i];
351                 *ptr++ = val;
352                 if (val == 0xf4) break;
353         }
354         return;
355 }
356                 
357 /*
358  * here we are really paranoid about faking a "real"
359  * BIOS. Most of this information was pulled from
360  * dosem.
361  */
362 static void
363 setup_int_vect(void)
364 {
365         const CARD16 cs = 0x0000;
366         const CARD16 ip = 0x0;
367         int i;
368         
369         /* let the int vects point to the SYS_BIOS seg */
370         for (i=0; i<0x80; i++) {
371                 ((CARD16*)0)[i<<1] = ip;
372                 ((CARD16*)0)[(i<<1)+1] = cs;
373         }
374         /* video interrupts default location */
375         ((CARD16*)0)[(0x42<<1)+1] = 0xf000;
376         ((CARD16*)0)[0x42<<1] = 0xf065;
377         ((CARD16*)0)[(0x10<<1)+1] = 0xf000;
378         ((CARD16*)0)[0x10<<1] = 0xf065;
379         /* video param table default location (int 1d) */
380         ((CARD16*)0)[(0x1d<<1)+1] = 0xf000;
381         ((CARD16*)0)[0x1d<<1] = 0xf0A4;
382         /* font tables default location (int 1F) */
383         ((CARD16*)0)[(0x1f<<1)+1] = 0xf000;
384         ((CARD16*)0)[0x1f<<1] = 0xfa6e;
385
386         /* int 11 default location */
387         ((CARD16*)0)[(0x11<1)+1] = 0xf000;
388         ((CARD16*)0)[0x11<<1] = 0xf84d;
389         /* int 12 default location */
390         ((CARD16*)0)[(0x12<<1)+1] = 0xf000;
391         ((CARD16*)0)[0x12<<1] = 0xf841;
392         /* int 15 default location */
393         ((CARD16*)0)[(0x15<<1)+1] = 0xf000;
394         ((CARD16*)0)[0x15<<1] = 0xf859;
395         /* int 1A default location */
396         ((CARD16*)0)[(0x1a<<1)+1] = 0xf000;
397         ((CARD16*)0)[0x1a<<1] = 0xff6e;
398         /* int 05 default location */
399         ((CARD16*)0)[(0x05<<1)+1] = 0xf000;
400         ((CARD16*)0)[0x05<<1] = 0xff54;
401         /* int 08 default location */
402         ((CARD16*)0)[(0x8<<1)+1] = 0xf000;
403         ((CARD16*)0)[0x8<<1] = 0xfea5;
404         /* int 13 default location (fdd) */
405         ((CARD16*)0)[(0x13<<1)+1] = 0xf000;
406         ((CARD16*)0)[0x13<<1] = 0xec59;
407         /* int 0E default location */
408         ((CARD16*)0)[(0xe<<1)+1] = 0xf000;
409         ((CARD16*)0)[0xe<<1] = 0xef57;
410         /* int 17 default location */
411         ((CARD16*)0)[(0x17<<1)+1] = 0xf000;
412         ((CARD16*)0)[0x17<<1] = 0xefd2;
413         /* fdd table default location (int 1e) */
414         ((CARD16*)0)[(0x1e<<1)+1] = 0xf000;
415         ((CARD16*)0)[0x1e<<1] = 0xefc7;
416 }
417
418 static int
419 setup_system_bios(void)
420 {
421         char *date = "06/01/99";
422         char *eisa_ident = "PCI/ISA";
423         
424 #if MAP_SYS_BIOS
425         if (!copy_sys_bios()) return 0;
426         return 1;
427 #endif
428 //    memset((void *)0xF0000,0xf4,0xfff7);
429         
430         /*
431          * we trap the "industry standard entry points" to the BIOS
432          * and all other locations by filling them with "hlt"
433          * TODO: implement hlt-handler for these
434          */
435         memset((void *)0xF0000,0xf4,0x10000);
436
437         /*
438          * TODO: we should copy the fdd table (0xfec59-0xfec5b)
439          * the video parameter table (0xf0ac-0xf0fb)
440          * and the font tables (0xfa6e-0xfe6d)
441          * from the original bios here
442          */
443         
444         /* set bios date */
445         strcpy((char *)0xFFFF5,date);
446         /* set up eisa ident string */
447         strcpy((char *)0xFFFD9,eisa_ident);
448         /* write system model id for IBM-AT */
449         ((char *)0)[0xFFFFE] = 0xfc;
450
451         return 1;
452 }
453
454 static int
455 chksum(CARD8 *start)
456 {
457   CARD16 size;
458   CARD8 val = 0;
459   int i;
460
461   size = *(start+2) * 512;      
462   for (i = 0; i<size; i++)
463     val += *(start + i);
464         
465   if (!val)
466     return 1;
467
468   log_err("BIOS chksum wrong\n");
469   return 0;
470 }