aboutsummaryrefslogtreecommitdiff
path: root/entry.S
blob: 9a9454a4d2efeb0b0cfca194cf94b4d2b1dfbc49 (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
/*
 * 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.
	 */
	orl	$X86_EFLAGS_CF, 0x4(%esp)

	IRET
ENTRY_END(bios_intfake)

/*
 * int 10 - video - service
 */
ENTRY(bios_int10)
	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

	/* Clear CF to indicate success.  */
	andl	$~X86_EFLAGS_CF, 0x4(%esp)

	IRET
ENTRY_END(bios_int10)

ENTRY(bios_int15)
	SAVE_BIOSREGS

	movl	%esp, %eax
	call	int15_handler

	RESTORE_BIOSREGS

	IRET
ENTRY_END(bios_int15)