aboutsummaryrefslogtreecommitdiff
path: root/entry.S
blob: 31d840bac721a13b334b432e9d703ce486a84e0f (plain)
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)