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/machine/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.
50 .long GRUB_MEMORY_MACHINE_PROT_STACK
57 DATA32 call real_to_prot
61 * This is the Global Descriptor Table
63 * An entry, a "Segment Descriptor", looks like this:
66 * ------------------------------------------------------------
67 * | | |B| |A| | | |1|0|E|W|A| |
68 * | BASE 31..24 |G|/|L|V| LIMIT |P|DPL| TYPE | BASE 23:16 | 4
69 * | | |D| |L| 19..16| | |1|1|C|R|A| |
70 * ------------------------------------------------------------
72 * | BASE 15..0 | LIMIT 15..0 | 0
74 * ------------------------------------------------------------
76 * Note the ordering of the data items is reversed from the above
80 .p2align 5 /* force 4-byte alignment */
86 * base = 0x00000000, limit = 0xFFFFF (4 KiB Granularity), present
87 * type = 32bit code execute/read, DPL = 0
90 .byte 0, 0x9A, 0xCF, 0
93 * base = 0x00000000, limit 0xFFFFF (4 KiB Granularity), present
94 * type = 32 bit data read/write, DPL = 0
97 .byte 0, 0x92, 0xCF, 0
99 /* -- 16 bit real mode CS --
100 * base = 0x00000000, limit 0x0FFFF (1 B Granularity), present
101 * type = 16 bit code execute/read only/conforming, DPL = 0
106 /* -- 16 bit real mode DS --
107 * base = 0x00000000, limit 0x0FFFF (1 B Granularity), present
108 * type = 16 bit data read/write, DPL = 0
115 /* this is the GDT descriptor */
117 .word 0x27 /* limit */
127 * These next two routines, "real_to_prot" and "prot_to_real" are structured
128 * in a very specific way. Be very careful when changing them.
130 * NOTE: Use of either one messes up %eax and %ebp.
137 /* load the GDT register */
140 DATA32 ADDR32 lgdt gdtdesc
142 /* turn on protected mode */
144 orl $GRUB_MEMORY_CPU_CR0_PE_ON, %eax
147 /* jump to relocation, flush prefetch queue, and reload %cs */
148 DATA32 ljmp $GRUB_MEMORY_MACHINE_PROT_MODE_CSEG, $protcseg
152 /* reload other segment registers */
153 movw $GRUB_MEMORY_MACHINE_PROT_MODE_DSEG, %ax
160 /* put the return address in a known safe location */
162 movl %eax, GRUB_MEMORY_MACHINE_REAL_STACK
164 /* get protected mode stack */
169 /* get return address onto the right stack */
170 movl GRUB_MEMORY_MACHINE_REAL_STACK, %eax
179 /* return on the old (or initialized) stack! */
182 * GRUB -- GRand Unified Bootloader
183 * Copyright (C) 1999,2000,2001,2002,2003,2005,2006,2007,2009,2010 Free Software Foundation, Inc.
185 * GRUB is free software: you can redistribute it and/or modify
186 * it under the terms of the GNU General Public License as published by
187 * the Free Software Foundation, either version 3 of the License, or
188 * (at your option) any later version.
190 * GRUB is distributed in the hope that it will be useful,
191 * but WITHOUT ANY WARRANTY; without even the implied warranty of
192 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
193 * GNU General Public License for more details.
195 * You should have received a copy of the GNU General Public License
196 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
200 /* just in case, set GDT */
206 /* save the protected mode stack */
210 /* get the return address */
212 movl %eax, GRUB_MEMORY_MACHINE_REAL_STACK
214 /* set up new stack */
215 movl $GRUB_MEMORY_MACHINE_REAL_STACK, %eax
219 /* set up segment limits */
220 movw $GRUB_MEMORY_MACHINE_PSEUDO_REAL_DSEG, %ax
227 /* this might be an extra step */
228 /* jump to a 16 bit segment */
229 ljmp $GRUB_MEMORY_MACHINE_PSEUDO_REAL_CSEG, $tmpcseg
234 /* clear the PE bit of CR0 */
236 andl $(~GRUB_MEMORY_CPU_CR0_PE_ON), %eax
239 /* flush prefetch queue, reload %cs */
240 DATA32 ljmp $0, $realcseg
243 /* we are in real mode now
244 * set up the real mode segment registers : DS, SS, ES
255 #ifdef GRUB_MACHINE_PCBIOS
256 /* restore interrupts */
260 /* return on new stack! */