summaryrefslogtreecommitdiffstats
path: root/grub-core/kern/i386/int.S
blob: 862a5420268ea1f38e751ece0349b8183ca41057 (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
/*
 *  GRUB  --  GRand Unified Bootloader
 *  Copyright (C) 2010,2011 Free Software Foundation, Inc.
 *
 *  GRUB is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  GRUB is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
 */

FUNCTION(grub_bios_interrupt)
	pushf
	cli
	popf
	pushl    %ebp
	pushl    %ecx
	pushl    %eax
	pushl    %ebx
	pushl    %esi
	pushl    %edi	
	pushl    %edx
	
	movb     %al, intno
	movl	 (%edx), %eax
	movl	 %eax, LOCAL(bios_register_eax)
	movw	 4(%edx), %ax
	movw	 %ax, LOCAL(bios_register_es)
	movw	 6(%edx), %ax
	movw	 %ax, LOCAL(bios_register_ds)
	movw	 8(%edx), %ax
	movw	 %ax, LOCAL(bios_register_flags)

	movl 	12(%edx), %ebx
	movl 	16(%edx), %ecx
	movl 	20(%edx), %edi
	movl 	24(%edx), %esi
	movl 	28(%edx), %edx

	/*
	Via C3 CPUs have cache coherence problems, so we need to call
	wbinvd at these 2 points. As wbinvd slows down boot, don't do
	it on non-VIA. 9090 is nop nop. */
VARIABLE(grub_bios_via_workaround1)
	.byte 0x90, 0x90

	PROT_TO_REAL
	.code16
	pushf
	cli
	
	mov	%ds, %ax
	push	%ax

	/* movw imm16, %ax*/
	.byte	0xb8
LOCAL(bios_register_es):
	.short 	0
	movw	%ax, %es
	/* movw imm16, %ax*/
	.byte	0xb8
LOCAL(bios_register_ds):
	.short 	0
	movw	%ax, %ds

	/* movw imm16, %ax*/
	.byte	0xb8
LOCAL(bios_register_flags):
	.short 	0
	push	%ax
	popf

	/* movl imm32, %eax*/
	.byte	0x66, 0xb8
LOCAL(bios_register_eax):
	.long 	0
	
	/* int imm8.  */
	.byte   0xcd
intno:	
	.byte   0

	movl 	%eax, %cs:LOCAL(bios_register_eax)
	movw	%ds, %ax
	movw 	%ax, %cs:LOCAL(bios_register_ds)
	pop 	%ax
	mov	%ax, %ds
	pushf
	pop	%ax
	movw	%ax, LOCAL(bios_register_flags)
	mov 	%es, %ax
	movw	%ax, LOCAL(bios_register_es)

	popf

VARIABLE(grub_bios_via_workaround2)
	.byte 0x90, 0x90

	REAL_TO_PROT
	.code32

	popl    %eax

	movl 	%ebx, 12(%eax)
	movl 	%ecx, 16(%eax)
	movl 	%edi, 20(%eax)
	movl 	%esi, 24(%eax)
	movl 	%edx, 28(%eax)

	movl     %eax, %edx

	movl	 LOCAL(bios_register_eax), %eax
	movl	 %eax, (%edx)
	movw	 LOCAL(bios_register_es), %ax
	movw	 %ax, 4(%edx)
	movw	 LOCAL(bios_register_ds), %ax
	movw	 %ax, 6(%edx)
	movw	 LOCAL(bios_register_flags), %ax
	movw	 %ax, 8(%edx)

	popl 	%edi
	popl 	%esi
	popl    %ebx
	popl    %eax
	popl    %ecx
	popl    %ebp
	ret