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
138
|
/*
* Our pretty trivial BIOS emulation
*/
#include "assembly.h"
#include "processor-flags.h"
.org 0
.code16gcc
/*
* handy BIOS macros
*/
/* If you change these macros, remember to update 'struct biosregs' */
.macro SAVE_BIOSREGS
pushl %fs
pushl %es
pushl %ds
pushl %edi
pushl %esi
pushl %ebp
pushl %esp
pushl %edx
pushl %ecx
pushl %ebx
pushl %eax
.endm
.macro RESTORE_BIOSREGS
popl %eax
popl %ebx
popl %ecx
popl %edx
popl %esp
popl %ebp
popl %esi
popl %edi
popl %ds
popl %es
popl %fs
.endm
ENTRY(bios_irq)
pushw %ax
mov $0x20, %al
out %al, $0x20
popw %ax
IRET
ENTRY_END(bios_irq)
/*
* fake interrupt handler, nothing can be faster ever
*/
ENTRY(bios_intfake)
/*
* Set CF to indicate failure. We don't want callers to think that the
* interrupt handler succeeded and then treat the return values in
* registers as valid data.
*/
orb $X86_EFLAGS_CF, 0x4(%esp)
IRET
ENTRY_END(bios_intfake)
/*
* int 10 - video - service
*/
ENTRY(bios_int10)
andb $~X86_EFLAGS_CF, 0x4(%esp)
SAVE_BIOSREGS
movl %esp, %eax
/* this is way easier than doing it in assembly */
/* just push all the regs and jump to a C handler */
call int10_handler
RESTORE_BIOSREGS
IRET
ENTRY_END(bios_int10)
ENTRY(bios_int15)
andb $~X86_EFLAGS_CF, 0x4(%esp)
SAVE_BIOSREGS
movl %esp, %eax
call int15_handler
RESTORE_BIOSREGS
IRET
ENTRY_END(bios_int15)
.code32
ENTRY(pcibios_entry)
clc
pushfl
SAVE_BIOSREGS
movl %esp, %eax
call pcibios_handler
RESTORE_BIOSREGS
popfl
lretl
ENTRY_END(pcibios_entry)
ENTRY(bios32_entry)
pushfl
testl %ebx, %ebx /* BIOS32 service directory? */
jnz 2f
cmp $0x49435024, %eax /* "$PCI"? */
movb $0x80, %al /* service not present */
jne 1f
xorl %ebx, %ebx /* fill in base/length/entry */
movl $(1 << 20), %ecx
movl $pcibios_entry, %edx
movb $0x00, %al /* service present */
1:
popfl
lretl
2:
movb $0x81, %al /* unimplemented function */
popfl
lretl
ENTRY_END(bios32_entry)
ENTRY(pic_base)
call 1f
2:
ret
1:
popl %eax
pushl %eax
subl $2b, %eax
ret /* return to 2b */
ENTRY_END(pic_base)
|