]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/i386/cpu/start.S
Merge branch 'master' of git://git.denx.de/u-boot-imx
[karo-tx-uboot.git] / arch / i386 / cpu / start.S
1 /*
2  *  U-boot - i386 Startup Code
3  *
4  *  Copyright (c) 2002  Omicron Ceti AB, Daniel Engström <denaiel@omicron.se>
5  *
6  * See file CREDITS for list of people who contributed to this
7  * project.
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License as
11  * published by the Free Software Foundation; either version 2 of
12  * the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
22  * MA 02111-1307 USA
23  */
24
25
26 #include <config.h>
27 #include <version.h>
28
29
30 .section .text
31 .code32
32 .globl _start
33 .type _start, @function
34 .globl _i386boot_start
35 _i386boot_start:
36         /*
37          * This is the fail safe 32-bit bootstrap entry point. The
38          * following code is not executed from a cold-reset (actually, a
39          * lot of it is, but from real-mode after cold reset. It is
40          * repeated here to put the board into a state as close to cold
41          * reset as necessary)
42          */
43         cli
44         cld
45
46         /* Turn of cache (this might require a 486-class CPU) */
47         movl    %cr0, %eax
48         orl     $0x60000000,%eax
49         movl    %eax, %cr0
50         wbinvd
51
52         /* Tell 32-bit code it is being entered from an in-RAM copy */
53         movw    $0x0000, %bx
54 _start:
55         /* This is the 32-bit cold-reset entry point */
56
57         movl    $0x18,%eax      /* Load our segement registes, the
58                                  * gdt have already been loaded by start16.S */
59         movw    %ax,%fs
60         movw    %ax,%ds
61         movw    %ax,%gs
62         movw    %ax,%es
63         movw    %ax,%ss
64
65         /* Clear the interupt vectors */
66         lidt    blank_idt_ptr
67
68         /*
69          * Skip low-level board and memory initialization if not starting
70          * from cold-reset. This allows us to do a fail safe boot-strap
71          * into a new build of U-Boot from a known-good boot flash
72          */
73         movw    $0x0001, %ax
74         cmpw    %ax, %bx
75         jne     mem_init_ret
76
77         /* We call a few functions in the board support package
78          * since we have no stack yet we'll have to use %ebp
79          * to store the return address */
80
81         /* Early platform init (setup gpio, etc ) */
82         mov     $early_board_init_ret, %ebp
83         jmp     early_board_init
84 early_board_init_ret:
85
86         /* The __port80 entry-point should be usabe by now */
87         /* so we try to indicate progress */
88         movw    $0x01, %ax
89         movl    $.progress0, %ebp
90         jmp     show_boot_progress_asm
91 .progress0:
92
93         /* size memory */
94         mov     $mem_init_ret, %ebp
95         jmp     mem_init
96 mem_init_ret:
97
98         /* fetch memory size (into %eax) */
99         mov     $get_mem_size_ret, %ebp
100         jmp     get_mem_size
101 get_mem_size_ret:
102
103         /*
104          * We are now in 'Flat Protected Mode' and we know how much memory
105          * the board has. The (temporary) Global Descriptor Table is not
106          * in a 'Safe' place (it is either in Flash which can be erased or
107          * reprogrammed or in a fail-safe boot-strap image which could be
108          * over-written).
109          *
110          * Move the final gdt to a safe place (top of RAM) and load it.
111          * This is not a trivial excercise - the lgdt instruction does not
112          * have a register operand (memory only) and we may well be
113          * running from Flash, so self modifying code will not work here.
114          * To overcome this, we copy a stub into upper memory along with
115          * the GDT.
116          */
117
118         /* Reduce upper memory limit by (Stub + GDT Pointer + GDT) */
119         subl    $(end_gdt_setup - start_gdt_setup), %eax
120
121         /* Copy the GDT and Stub */
122         movl    $start_gdt_setup, %esi
123         movl    %eax, %edi
124         movl    $(end_gdt_setup - start_gdt_setup), %ecx
125         shrl    $2, %ecx
126         cld
127         rep     movsl
128
129         /* write the lgdt 'parameter' */
130         subl    $(jmp_instr - start_gdt_setup - 4), %ebp
131         addl    %eax, %ebp
132         movl    $(gdt_ptr - start_gdt_setup), %ebx
133         addl    %eax, %ebx
134         movl    %ebx, (%ebp)
135
136         /* write the gdt address into the pointer */
137         movl    $(gdt_addr - start_gdt_setup), %ebp
138         addl    %eax, %ebp
139         movl    $(gdt - start_gdt_setup), %ebx
140         addl    %eax, %ebx
141         movl    %ebx, (%ebp)
142
143         /* Save the return address */
144         movl    $load_gdt_ret, %ebp
145
146         /* Load the new (safe) Global Descriptor Table */
147         jmp     *%eax
148
149 load_gdt_ret:
150         /* Check we have enough memory for stack */
151         movl    $CONFIG_SYS_STACK_SIZE, %ecx
152         cmpl    %ecx, %eax
153         jae     mem_ok
154
155         /* indicate (lack of) progress */
156         movw    $0x81, %ax
157         movl    $.progress0a, %ebp
158         jmp     show_boot_progress_asm
159 .progress0a:
160         jmp     die
161 mem_ok:
162         /* Set stack pointer to upper memory limit*/
163         movl    %eax, %esp
164
165         /* indicate progress */
166         movw    $0x02, %ax
167         movl    $.progress1, %ebp
168         jmp     show_boot_progress_asm
169 .progress1:
170
171         /* Test the stack */
172         pushl   $0
173         popl    %eax
174         cmpl    $0, %eax
175         jne     no_stack
176         push    $0x55aa55aa
177         popl    %ebx
178         cmpl    $0x55aa55aa, %ebx
179         je      stack_ok
180
181 no_stack:
182         /* indicate (lack of) progress */
183         movw    $0x82, %ax
184         movl    $.progress1a, %ebp
185         jmp     show_boot_progress_asm
186 .progress1a:
187         jmp die
188
189
190 stack_ok:
191         /* indicate progress */
192         movw    $0x03, %ax
193         movl    $.progress2, %ebp
194         jmp     show_boot_progress_asm
195 .progress2:
196
197         wbinvd
198
199         /* Get upper memory limit */
200         movl %esp, %ecx
201         subl $CONFIG_SYS_STACK_SIZE, %ecx
202
203         /* Create a Stack Frame */
204         pushl %ebp
205         movl %esp, %ebp
206
207         /* stack_limit parameter */
208         pushl   %ecx
209         call    board_init_f    /* Enter, U-boot! */
210
211         /* indicate (lack of) progress */
212         movw    $0x85, %ax
213         movl    $.progress4a, %ebp
214         jmp     show_boot_progress_asm
215 .progress4a:
216
217 die:    hlt
218         jmp     die
219         hlt
220
221 blank_idt_ptr:
222         .word   0               /* limit */
223         .long   0               /* base */
224
225 .align 4
226 start_gdt_setup:
227         lgdt    gdt_ptr
228 jmp_instr:
229         jmp     *%ebp
230
231 .align 4
232 gdt_ptr:
233         .word   0x30            /* limit (48 bytes = 6 GDT entries) */
234 gdt_addr:
235         .long   gdt             /* base */
236
237         /* The GDT table ...
238          *
239          *       Selector       Type
240          *       0x00           NULL
241          *       0x08           Unused
242          *       0x10           32bit code
243          *       0x18           32bit data/stack
244          *       0x20           16bit code
245          *       0x28           16bit data/stack
246          */
247
248 .align 4
249 gdt:
250         .word   0, 0, 0, 0      /* NULL  */
251         .word   0, 0, 0, 0      /* unused */
252
253         .word   0xFFFF          /* 4Gb - (0x100000*0x1000 = 4Gb) */
254         .word   0               /* base address = 0 */
255         .word   0x9B00          /* code read/exec */
256         .word   0x00CF          /* granularity = 4096, 386 (+5th nibble of limit) */
257
258         .word   0xFFFF          /* 4Gb - (0x100000*0x1000 = 4Gb) */
259         .word   0x0             /* base address = 0 */
260         .word   0x9300          /* data read/write */
261         .word   0x00CF          /* granularity = 4096, 386 (+5th nibble of limit) */
262
263         .word   0xFFFF          /* 64kb */
264         .word   0               /* base address = 0 */
265         .word   0x9b00          /* data read/write */
266         .word   0x0010          /* granularity = 1  (+5th nibble of limit) */
267
268         .word   0xFFFF          /* 64kb */
269         .word   0               /* base address = 0 */
270         .word   0x9300          /* data read/write */
271         .word   0x0010          /* granularity = 1 (+5th nibble of limit) */
272 end_gdt_setup: