2
* GRUB -- GRand Unified Bootloader
3
* Copyright (C) 1999,2000,2001,2002,2003,2005,2006,2007,2009,2010 Free Software Foundation, Inc.
5
* GRUB is free software: you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation, either version 3 of the License, or
8
* (at your option) any later version.
10
* GRUB is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
19
#include <grub/i386/pc/memory.h>
22
* Note: These functions defined in this file may be called from C.
23
* Be careful of that you must not modify some registers. Quote
24
* from gcc-2.95.2/gcc/config/i386/i386.h:
26
1 for registers not available across function calls.
27
These must include the FIXED_REGISTERS and also any
28
registers that can be used without being saved.
29
The latter must include the registers where values are returned
30
and the register where structure-value addresses are passed.
31
Aside from that, you can include as many other registers as you like.
33
ax,dx,cx,bx,si,di,bp,sp,st,st1,st2,st3,st4,st5,st6,st7,arg
34
{ 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }
38
* Note: GRUB is compiled with the options -mrtd and -mregparm=3.
39
* So the first three arguments are passed in %eax, %edx, and %ecx,
40
* respectively, and if a function has a fixed number of arguments
41
* and the number if greater than three, the function must return
42
* with "ret $N" where N is ((the number of arguments) - 3) * 4.
46
* This is the area for all of the special variables.
49
.p2align 2 /* force 4-byte alignment */
52
.long GRUB_MEMORY_MACHINE_PROT_STACK
55
* This is the Global Descriptor Table
57
* An entry, a "Segment Descriptor", looks like this:
60
* ------------------------------------------------------------
61
* | | |B| |A| | | |1|0|E|W|A| |
62
* | BASE 31..24 |G|/|L|V| LIMIT |P|DPL| TYPE | BASE 23:16 | 4
63
* | | |D| |L| 19..16| | |1|1|C|R|A| |
64
* ------------------------------------------------------------
66
* | BASE 15..0 | LIMIT 15..0 | 0
68
* ------------------------------------------------------------
70
* Note the ordering of the data items is reversed from the above
74
.p2align 2 /* force 4-byte alignment */
80
* base = 0x00000000, limit = 0xFFFFF (4 KiB Granularity), present
81
* type = 32bit code execute/read, DPL = 0
84
.byte 0, 0x9A, 0xCF, 0
87
* base = 0x00000000, limit 0xFFFFF (4 KiB Granularity), present
88
* type = 32 bit data read/write, DPL = 0
91
.byte 0, 0x92, 0xCF, 0
93
/* -- 16 bit real mode CS --
94
* base = 0x00000000, limit 0x0FFFF (1 B Granularity), present
95
* type = 16 bit code execute/read only/conforming, DPL = 0
100
/* -- 16 bit real mode DS --
101
* base = 0x00000000, limit 0x0FFFF (1 B Granularity), present
102
* type = 16 bit data read/write, DPL = 0
108
/* this is the GDT descriptor */
110
.word 0x27 /* limit */
114
* These next two routines, "real_to_prot" and "prot_to_real" are structured
115
* in a very specific way. Be very careful when changing them.
117
* NOTE: Use of either one messes up %eax and %ebp.
124
/* load the GDT register */
127
DATA32 ADDR32 lgdt gdtdesc
129
/* turn on protected mode */
131
orl $GRUB_MEMORY_CPU_CR0_PE_ON, %eax
134
/* jump to relocation, flush prefetch queue, and reload %cs */
135
DATA32 ljmp $GRUB_MEMORY_MACHINE_PROT_MODE_CSEG, $protcseg
139
/* reload other segment registers */
140
movw $GRUB_MEMORY_MACHINE_PROT_MODE_DSEG, %ax
147
/* put the return address in a known safe location */
149
movl %eax, GRUB_MEMORY_MACHINE_REAL_STACK
151
/* get protected mode stack */
156
/* get return address onto the right stack */
157
movl GRUB_MEMORY_MACHINE_REAL_STACK, %eax
163
/* return on the old (or initialized) stack! */
167
/* just in case, set GDT */
170
/* save the protected mode stack */
174
/* get the return address */
176
movl %eax, GRUB_MEMORY_MACHINE_REAL_STACK
178
/* set up new stack */
179
movl $GRUB_MEMORY_MACHINE_REAL_STACK, %eax
183
/* set up segment limits */
184
movw $GRUB_MEMORY_MACHINE_PSEUDO_REAL_DSEG, %ax
191
/* this might be an extra step */
192
/* jump to a 16 bit segment */
193
ljmp $GRUB_MEMORY_MACHINE_PSEUDO_REAL_CSEG, $tmpcseg
198
/* clear the PE bit of CR0 */
200
andl $(~GRUB_MEMORY_CPU_CR0_PE_ON), %eax
203
/* flush prefetch queue, reload %cs */
204
DATA32 ljmp $0, $realcseg
207
/* we are in real mode now
208
* set up the real mode segment registers : DS, SS, ES
219
#ifdef GRUB_MACHINE_PCBIOS
220
/* restore interrupts */
224
/* return on new stack! */
232
* Reboot the system. At the moment, rely on BIOS.
234
FUNCTION(grub_reboot)
238
/* set 0x472 to 0x0000 for cold boot (0x1234 for warm boot) */
241
ljmp $0xf000, $0xfff0