Upgraded GRUB2 to 2.00 release.
[AROS.git] / arch / all-pc / boot / grub2-aros / grub-core / kern / i386 / realmode.S
blob6403b96992e1aa8a94bdcdef1631b764cbb49e8d
1 /*
2  *  GRUB  --  GRand Unified Bootloader
3  *  Copyright (C) 1999,2000,2001,2002,2003,2005,2006,2007,2009,2010 Free Software Foundation, Inc.
4  *
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.
9  *
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.
14  *
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/>.
17  */
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 }
35  */
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.
43  */
46  *  This is the area for all of the special variables.
47  */
49 protstack:
50         .long   GRUB_MEMORY_MACHINE_PROT_STACK
52         .macro PROT_TO_REAL
53         call    prot_to_real
54         .endm
56         .macro REAL_TO_PROT
57         DATA32  call    real_to_prot
58         .endm
61  * This is the Global Descriptor Table
62  *
63  *  An entry, a "Segment Descriptor", looks like this:
64  *
65  * 31          24         19   16                 7           0
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  * ------------------------------------------------------------
71  * |                             |                            |
72  * |        BASE 15..0           |       LIMIT 15..0          |  0
73  * |                             |                            |
74  * ------------------------------------------------------------
75  *
76  *  Note the ordering of the data items is reversed from the above
77  *  description.
78  */
80         .p2align        5       /* force 4-byte alignment */
81 gdt:
82         .word   0, 0
83         .byte   0, 0, 0, 0
85         /* -- code segment --
86          * base = 0x00000000, limit = 0xFFFFF (4 KiB Granularity), present
87          * type = 32bit code execute/read, DPL = 0
88          */
89         .word   0xFFFF, 0
90         .byte   0, 0x9A, 0xCF, 0
92         /* -- data segment --
93          * base = 0x00000000, limit 0xFFFFF (4 KiB Granularity), present
94          * type = 32 bit data read/write, DPL = 0
95          */
96         .word   0xFFFF, 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
102          */
103         .word   0xFFFF, 0
104         .byte   0, 0x9E, 0, 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
109          */
110         .word   0xFFFF, 0
111         .byte   0, 0x92, 0, 0
114         .p2align 5
115 /* this is the GDT descriptor */
116 gdtdesc:
117         .word   0x27                    /* limit */
118         .long   gdt                     /* addr */
119 LOCAL(realidt):
120         .word 0x400
121         .long 0
122 protidt:
123         .word 0
124         .long 0
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.
131  */
133 real_to_prot:
134         .code16
135         cli
137         /* load the GDT register */
138         xorw    %ax, %ax
139         movw    %ax, %ds
140         DATA32  ADDR32  lgdt    gdtdesc
142         /* turn on protected mode */
143         movl    %cr0, %eax
144         orl     $GRUB_MEMORY_CPU_CR0_PE_ON, %eax
145         movl    %eax, %cr0
147         /* jump to relocation, flush prefetch queue, and reload %cs */
148         DATA32  ljmp    $GRUB_MEMORY_MACHINE_PROT_MODE_CSEG, $protcseg
150         .code32
151 protcseg:
152         /* reload other segment registers */
153         movw    $GRUB_MEMORY_MACHINE_PROT_MODE_DSEG, %ax
154         movw    %ax, %ds
155         movw    %ax, %es
156         movw    %ax, %fs
157         movw    %ax, %gs
158         movw    %ax, %ss
160         /* put the return address in a known safe location */
161         movl    (%esp), %eax
162         movl    %eax, GRUB_MEMORY_MACHINE_REAL_STACK
164         /* get protected mode stack */
165         movl    protstack, %eax
166         movl    %eax, %esp
167         movl    %eax, %ebp
169         /* get return address onto the right stack */
170         movl    GRUB_MEMORY_MACHINE_REAL_STACK, %eax
171         movl    %eax, (%esp)
173         /* zero %eax */
174         xorl    %eax, %eax
176         sidt LOCAL(realidt)
177         lidt protidt
179         /* return on the old (or initialized) stack! */
180         ret
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/>.
197  */
199 #include <grub/i386/pc/memory.h>
201 prot_to_real:
202         /* just in case, set GDT */
203         lgdt    gdtdesc
205         sidt    protidt
206         lidt    LOCAL(realidt)
208         /* save the protected mode stack */
209         movl    %esp, %eax
210         movl    %eax, protstack
212         /* get the return address */
213         movl    (%esp), %eax
214         movl    %eax, GRUB_MEMORY_MACHINE_REAL_STACK
216         /* set up new stack */
217         movl    $GRUB_MEMORY_MACHINE_REAL_STACK, %eax
218         movl    %eax, %esp
219         movl    %eax, %ebp
221         /* set up segment limits */
222         movw    $GRUB_MEMORY_MACHINE_PSEUDO_REAL_DSEG, %ax
223         movw    %ax, %ds
224         movw    %ax, %es
225         movw    %ax, %fs
226         movw    %ax, %gs
227         movw    %ax, %ss
229         /* this might be an extra step */
230         /* jump to a 16 bit segment */
231         ljmp    $GRUB_MEMORY_MACHINE_PSEUDO_REAL_CSEG, $tmpcseg
233 tmpcseg:
234         .code16
236         /* clear the PE bit of CR0 */
237         movl    %cr0, %eax
238         andl    $(~GRUB_MEMORY_CPU_CR0_PE_ON), %eax
239         movl    %eax, %cr0
241         /* flush prefetch queue, reload %cs */
242         DATA32  ljmp    $0, $realcseg
244 realcseg:
245         /* we are in real mode now
246          * set up the real mode segment registers : DS, SS, ES
247          */
248         /* zero %eax */
249         xorl    %eax, %eax
251         movw    %ax, %ds
252         movw    %ax, %es
253         movw    %ax, %fs
254         movw    %ax, %gs
255         movw    %ax, %ss
257 #ifdef GRUB_MACHINE_PCBIOS
258         /* restore interrupts */
259         sti
260 #endif
262         /* return on new stack! */
263         DATA32  ret
265         .code32