]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/pc/bios32.c
merge
[plan9front.git] / sys / src / 9 / pc / bios32.c
1 #include "u.h"
2 #include "../port/lib.h"
3 #include "mem.h"
4 #include "dat.h"
5 #include "fns.h"
6 #include "io.h"
7
8 #define VFLAG(...)      if(vflag) print(__VA_ARGS__)
9
10 #define UPTR2INT(p)     ((uintptr)(p))
11
12 #define l16get(p)       (((p)[1]<<8)|(p)[0])
13 #define l32get(p)       (((u32int)l16get(p+2)<<16)|l16get(p))
14
15 static int vflag = 0;
16
17 typedef struct BIOS32sdh {              /* BIOS32 Service Directory Header */
18         u8int   signature[4];           /* "_32_" */
19         u8int   physaddr[4];            /* physical address of entry point */
20         u8int   revision;
21         u8int   length;                 /* of header in paragraphs */
22         u8int   checksum;               /* */
23         u8int   reserved[5];
24 } BIOS32sdh;
25
26 typedef struct BIOS32si {               /* BIOS32 Service Interface */
27         u8int*  base;                   /* base address of service */
28         int     length;                 /* length of service */
29         u32int  offset;                 /* service entry-point from base */
30
31         u16int  ptr[3];                 /* far pointer m16:32 */
32 } BIOS32si;
33
34 static Lock bios32lock;
35 static u16int bios32ptr[3];
36 static void* bios32entry;
37
38 int
39 bios32ci(BIOS32si* si, BIOS32ci* ci)
40 {
41         int r;
42
43         lock(&bios32lock);
44         r = bios32call(ci, si->ptr);
45         unlock(&bios32lock);
46
47         return r;
48 }
49
50 static int
51 bios32locate(void)
52 {
53         uintptr ptr;
54         BIOS32sdh *sdh;
55
56         VFLAG("bios32link\n");
57         if((sdh = sigsearch("_32_")) == nil)
58                 return -1;
59         if(checksum(sdh, sizeof(BIOS32sdh)))
60                 return -1;
61         VFLAG("sdh @ %#p, entry %#ux\n", sdh, l32get(sdh->physaddr));
62
63         bios32entry = vmap(l32get(sdh->physaddr), 4096+1);
64         VFLAG("entry @ %#p\n", bios32entry);
65         ptr = UPTR2INT(bios32entry);
66         bios32ptr[0] = ptr & 0xffff;
67         bios32ptr[1] = (ptr>>16) & 0xffff;
68         bios32ptr[2] = KESEL;
69         VFLAG("bios32link: ptr %ux %ux %ux\n",
70                 bios32ptr[0], bios32ptr[1], bios32ptr[2]);
71
72         return 0;
73 }
74
75 void
76 BIOS32close(BIOS32si* si)
77 {
78         vunmap(si->base, si->length);
79         free(si);
80 }
81
82 BIOS32si*
83 bios32open(char* id)
84 {
85         uint ptr;
86         BIOS32ci ci;
87         BIOS32si *si;
88
89         lock(&bios32lock);
90         if(bios32ptr[2] == 0 && bios32locate() < 0){
91                 unlock(&bios32lock);
92                 return nil;
93         }
94
95         VFLAG("bios32si: %s\n", id);
96         memset(&ci, 0, sizeof(BIOS32ci));
97         ci.eax = (id[3]<<24|(id[2]<<16)|(id[1]<<8)|id[0]);
98
99         bios32call(&ci, bios32ptr);
100         unlock(&bios32lock);
101
102         VFLAG("bios32si: eax %ux\n", ci.eax);
103         if(ci.eax & 0xff)
104                 return nil;
105         VFLAG("bios32si: base %#ux length %#ux offset %#ux\n",
106                 ci.ebx, ci.ecx, ci.edx);
107
108         if((si = malloc(sizeof(BIOS32si))) == nil)
109                 return nil;
110         if((si->base = vmap(ci.ebx, ci.ecx)) == nil){
111                 free(si);
112                 return nil;
113         }
114         si->length = ci.ecx;
115
116         ptr = UPTR2INT(si->base)+ci.edx;
117         si->ptr[0] = ptr & 0xffff;
118         si->ptr[1] = (ptr>>16) & 0xffff;
119         si->ptr[2] = KESEL;
120         VFLAG("bios32si: eax entry %ux\n", ptr);
121
122         return si;
123 }