Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
static int vflag = 0;
13
 
14
typedef struct BIOS32sdh {		/* BIOS32 Service Directory Header */
15
	u8int	signature[4];		/* "_32_" */
16
	u8int	physaddr[4];		/* physical address of entry point */
17
	u8int	revision;
18
	u8int	length;			/* of header in paragraphs */
19
	u8int	checksum;		/* */
20
	u8int	reserved[5];
21
} BIOS32sdh;
22
 
23
typedef struct BIOS32si {		/* BIOS32 Service Interface */
24
	u8int*	base;			/* base address of service */
25
	int	length;			/* length of service */
26
	u32int	offset;			/* service entry-point from base */
27
 
28
	u16int	ptr[3];			/* far pointer m16:32 */
29
} BIOS32si;
30
 
31
static Lock bios32lock;
32
static u16int bios32ptr[3];
33
static void* bios32entry;
34
 
35
int
36
bios32ci(BIOS32si* si, BIOS32ci* ci)
37
{
38
	int r;
39
 
40
	lock(&bios32lock);
41
	r = bios32call(ci, si->ptr);
42
	unlock(&bios32lock);
43
 
44
	return r;
45
}
46
 
47
static void*
48
rsdchecksum(void* addr, int length)
49
{
50
	u8int *p, sum;
51
 
52
	sum = 0;
53
	for(p = addr; length-- > 0; p++)
54
		sum += *p;
55
	if(sum == 0)
56
		return addr;
57
 
58
	return nil;
59
}
60
 
61
static void*
62
rsdscan(u8int* addr, int len, char* signature)
63
{
64
	int sl;
65
	u8int *e, *p;
66
 
67
	e = addr+len;
68
	sl = strlen(signature);
69
	for(p = addr; p+sl < e; p += 16){
70
		if(memcmp(p, signature, sl))
71
			continue;
72
		return p;
73
	}
74
 
75
	return nil;
76
}
77
 
78
static int
79
bios32locate(void)
80
{
81
	uintptr ptr;
82
	BIOS32sdh *sdh;
83
 
84
	VFLAG("bios32link\n");
85
	if((sdh = rsdscan(BIOSSEG(0xE000), 0x20000, "_32_")) == nil)
86
		return -1;
87
	if(rsdchecksum(sdh, sizeof(BIOS32sdh)) == nil)
88
		return -1;
89
	VFLAG("sdh @ %#p, entry %#ux\n", sdh, L32GET(sdh->physaddr));
90
 
91
	bios32entry = vmap(L32GET(sdh->physaddr), 4096+1);
92
	VFLAG("entry @ %#p\n", bios32entry);
93
	ptr = UPTR2INT(bios32entry);
94
	bios32ptr[0] = ptr & 0xffff;
95
	bios32ptr[1] = (ptr>>16) & 0xffff;
96
	bios32ptr[2] = KESEL;
97
	VFLAG("bios32link: ptr %ux %ux %ux\n",
98
		bios32ptr[0], bios32ptr[1], bios32ptr[2]);
99
 
100
	return 0;
101
}
102
 
103
void
104
BIOS32close(BIOS32si* si)
105
{
106
	vunmap(si->base, si->length);
107
	free(si);
108
}
109
 
110
BIOS32si*
111
bios32open(char* id)
112
{
113
	uint ptr;
114
	BIOS32ci ci;
115
	BIOS32si *si;
116
 
117
	lock(&bios32lock);
118
	if(bios32ptr[2] == 0 && bios32locate() < 0){
119
		unlock(&bios32lock);
120
		return nil;
121
	}
122
 
123
	VFLAG("bios32si: %s\n", id);
124
	memset(&ci, 0, sizeof(BIOS32ci));
125
	ci.eax = (id[3]<<24|(id[2]<<16)|(id[1]<<8)|id[0]);
126
 
127
	bios32call(&ci, bios32ptr);
128
	unlock(&bios32lock);
129
 
130
	VFLAG("bios32si: eax %ux\n", ci.eax);
131
	if(ci.eax & 0xff)
132
		return nil;
133
	VFLAG("bios32si: base %#ux length %#ux offset %#ux\n",
134
		ci.ebx, ci.ecx, ci.edx);
135
 
136
	if((si = malloc(sizeof(BIOS32si))) == nil)
137
		return nil;
138
	if((si->base = vmap(ci.ebx, ci.ecx)) == nil){
139
		free(si);
140
		return nil;
141
	}
142
	si->length = ci.ecx;
143
 
144
	ptr = UPTR2INT(si->base)+ci.edx;
145
	si->ptr[0] = ptr & 0xffff;
146
	si->ptr[1] = (ptr>>16) & 0xffff;
147
	si->ptr[2] = KESEL;
148
	VFLAG("bios32si: eax entry %ux\n", ptr);
149
 
150
	return si;
151
}