[prefix] Move flatten_real_mode to libflat.S
[people/pcmattman/gpxe.git] / src / arch / i386 / transitions / libflat.S
1 /*
2  * Copyright (C) 2010 Michael Brown <mbrown@fensystems.co.uk>.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  *
18  */
19
20 FILE_LICENCE ( GPL2_OR_LATER )
21
22         .arch i386
23
24 #define CR0_PE 1
25
26 /****************************************************************************
27  * flatten_real_mode (real-mode far call)
28  *
29  * Set up 4GB segment limits
30  *
31  * Parameters:
32  *   none
33  * Returns:
34  *   none
35  * Corrupts:
36  *   none
37  ****************************************************************************
38  */
39         /* GDT for protected-mode calls */
40         .section ".text16.early.data", "aw", @progbits
41         .align 16
42 flatten_gdt:
43 flatten_gdt_limit:      .word flatten_gdt_length - 1
44 flatten_gdt_base:       .long 0
45                         .word 0 /* padding */
46 flatten_cs:     /* 16-bit protected-mode flat code segment */
47         .equ    FLAT_CS, flatten_cs - flatten_gdt
48         .word   0xffff, 0
49         .byte   0, 0x9b, 0x8f, 0
50 flatten_ss:     /* 16-bit protected-mode flat stack segment */
51         .equ    FLAT_SS, flatten_ss - flatten_gdt
52         .word   0xffff, 0
53         .byte   0, 0x93, 0x8f, 0
54 flatten_gdt_end:
55         .equ    flatten_gdt_length, . - flatten_gdt
56         .size   flatten_gdt, . - flatten_gdt
57
58         .section ".text16.early.data", "aw", @progbits
59         .align 16
60 flatten_saved_gdt:
61         .long   0, 0
62         .size   flatten_saved_gdt, . - flatten_saved_gdt
63
64         .section ".text16.early", "awx", @progbits
65         .code16
66         .globl  flatten_real_mode
67 flatten_real_mode:
68         /* Preserve registers and flags */
69         pushfl
70         pushl   %eax
71         pushw   %si
72         pushw   %gs
73         pushw   %fs
74         pushw   %es
75         pushw   %ds
76         pushw   %ss
77
78         /* Set %ds for access to .text16.early.data variables */
79         pushw   %cs
80         popw    %ds
81
82         /* Preserve original GDT */
83         sgdt flatten_saved_gdt
84
85         /* Set up GDT bases */
86         xorl    %eax, %eax
87         movw    %cs, %ax
88         shll    $4, %eax
89         addl    $flatten_gdt, %eax
90         movl    %eax, flatten_gdt_base
91         movw    %cs, %ax
92         movw    $flatten_cs, %si
93         call    set_seg_base
94         movw    %ss, %ax
95         movw    $flatten_ss, %si
96         call    set_seg_base
97
98         /* Switch temporarily to protected mode and set segment registers */
99         pushw   %cs
100         pushw   $2f
101         cli
102         data32 lgdt flatten_gdt
103         movl    %cr0, %eax
104         orb     $CR0_PE, %al
105         movl    %eax, %cr0
106         ljmp    $FLAT_CS, $1f
107 1:      movw    $FLAT_SS, %ax
108         movw    %ax, %ss
109         movw    %ax, %ds
110         movw    %ax, %es
111         movw    %ax, %fs
112         movw    %ax, %gs
113         movl    %cr0, %eax
114         andb    $0!CR0_PE, %al
115         movl    %eax, %cr0
116         lret
117 2:      /* lret will ljmp to here */
118
119         /* Restore GDT, registers and flags */
120         data32 lgdt flatten_saved_gdt
121         popw    %ss
122         popw    %ds
123         popw    %es
124         popw    %fs
125         popw    %gs
126         popw    %si
127         popl    %eax
128         popfl
129         lret
130         .size flatten_real_mode, . - flatten_real_mode
131
132         .section ".text16.early", "awx", @progbits
133         .code16
134 set_seg_base:
135         rolw    $4, %ax
136         movw    %ax, 2(%si)
137         andw    $0xfff0, 2(%si)
138         movb    %al, 4(%si)
139         andb    $0x0f, 4(%si)
140         ret
141         .size set_seg_base, . - set_seg_base