1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
|
#include <types.h>
#include <io.h>
#include <x86emu.h>
#include <x86glue.h>
void printk(const char *fmt, ...);
void x86emu_dump_xregs(void);
void pci_init(void);
int int10_handler(void);
int int1a_handler(void);
void pushw(u16 val);
unsigned char biosmem[1024 * 1024];
int verbose = 0;
u8 x_inb(u16 port)
{
return inb(port);
}
u16 x_inw(u16 port)
{
return inw(port);
}
u32 x_inl(u16 port)
{
return inb(port);
}
void x_outb(u16 port, u8 val)
{
outb(port, val);
}
void x_outw(u16 port, u16 val)
{
outb(port, val);
}
void x_outl(u16 port, u32 val)
{
outb(port, val);
}
X86EMU_pioFuncs myfuncs = {
x_inb, x_inw, x_inl,
x_outb, x_outw, x_outl
};
void irq_multiplexer(int num)
{
int ret = 0;
switch (num) {
case 0x10:
case 0x42:
case 0x6d:
ret = int10_handler();
break;
case 0x1a:
ret = int1a_handler();
break;
default:
break;
}
if (!ret) {
printk("int%x not implemented\n", num);
x86emu_dump_xregs();
}
}
ptr current = 0;
int startrom(unsigned char *addr)
{
X86EMU_intrFuncs intFuncs[256];
void X86EMU_setMemBase(void *base, size_t size);
int trace = 1;
int i;
int devfn=0x18; // FIXME
int size=64*1024; // FIXME
int initialcs=0xc000;
int initialip=0x0003;
int base=0xc0000;
X86EMU_setMemBase(biosmem, sizeof(biosmem));
X86EMU_setupPioFuncs(&myfuncs);
pci_init();
for (i = 0; i < 256; i++)
intFuncs[i] = irq_multiplexer;
X86EMU_setupIntrFuncs(intFuncs);
current->ax = devfn ? devfn : 0xff; // FIXME
/* above we need to search the device on the bus */
current->dx = 0x80;
// current->ip = 0;
for (i = 0; i < size; i++)
wrb(base + i, addr[i]);
/* cpu setup */
X86_AX = devfn ? devfn : 0xff;
X86_DX = 0x80;
X86_EIP = initialip;
X86_CS = initialcs;
/* Initialize stack and data segment */
X86_SS = 0x0030;
X86_DS = 0x0040;
X86_SP = 0xfffe;
/* We need a sane way to return from bios
* execution. A hlt instruction and a pointer
* to it, both kept on the stack, will do.
*/
pushw(0xf4f4); /* hlt; hlt */
pushw(X86_SS);
pushw(X86_SP + 2);
X86_ES = 0x0000;
if (trace) {
printk("Switching to single step mode.\n");
X86EMU_trace_on();
}
X86EMU_exec();
return 0;
}
|