]> git.sur5r.net Git - u-boot/blob - arch/x86/cpu/start.S
SPDX: Convert all of our single license tags to Linux Kernel style
[u-boot] / arch / x86 / cpu / start.S
1 /* SPDX-License-Identifier: GPL-2.0+ */
2 /*
3  *  U-Boot - x86 Startup Code
4  *
5  * (C) Copyright 2008-2011
6  * Graeme Russ, <graeme.russ@gmail.com>
7  *
8  * (C) Copyright 2002
9  * Daniel Engström, Omicron Ceti AB, <daniel@omicron.se>
10  */
11
12 #include <config.h>
13 #include <asm/global_data.h>
14 #include <asm/post.h>
15 #include <asm/processor.h>
16 #include <asm/processor-flags.h>
17 #include <generated/generic-asm-offsets.h>
18 #include <generated/asm-offsets.h>
19
20 .section .text
21 .code32
22 .globl _start
23 .type _start, @function
24 .globl _x86boot_start
25 _x86boot_start:
26         /*
27          * This is the fail-safe 32-bit bootstrap entry point.
28          *
29          * This code is used when booting from another boot loader like
30          * coreboot or EFI. So we repeat some of the same init found in
31          * start16.
32          */
33         cli
34         cld
35
36         /* Turn off cache (this might require a 486-class CPU) */
37         movl    %cr0, %eax
38         orl     $(X86_CR0_NW | X86_CR0_CD), %eax
39         movl    %eax, %cr0
40         wbinvd
41
42         /* Tell 32-bit code it is being entered from an in-RAM copy */
43         movl    $GD_FLG_WARM_BOOT, %ebx
44
45         /*
46          * Zero the BIST (Built-In Self Test) value since we don't have it.
47          * It must be 0 or the previous loader would have reported an error.
48          */
49         movl    $0, %ebp
50
51         jmp     1f
52
53         /* Add a way for tools to discover the _start entry point */
54         .align  4
55         .long   0x12345678
56 _start:
57         /*
58          * This is the 32-bit cold-reset entry point, coming from start16.
59          * Set %ebx to GD_FLG_COLD_BOOT to indicate this.
60          */
61         movl    $GD_FLG_COLD_BOOT, %ebx
62
63         /* Save BIST */
64         movl    %eax, %ebp
65 1:
66
67         /* Save table pointer */
68         movl    %ecx, %esi
69
70 #ifdef CONFIG_X86_LOAD_FROM_32_BIT
71         lgdt    gdt_ptr2
72 #endif
73
74         /* Load the segement registers to match the GDT loaded in start16.S */
75         movl    $(X86_GDT_ENTRY_32BIT_DS * X86_GDT_ENTRY_SIZE), %eax
76         movw    %ax, %fs
77         movw    %ax, %ds
78         movw    %ax, %gs
79         movw    %ax, %es
80         movw    %ax, %ss
81
82         /* Clear the interrupt vectors */
83         lidt    blank_idt_ptr
84
85         /*
86          * Critical early platform init - generally not used, we prefer init
87          * to happen later when we have a console, in case something goes
88          * wrong.
89          */
90         jmp     early_board_init
91 .globl early_board_init_ret
92 early_board_init_ret:
93         post_code(POST_START)
94
95         /* Initialise Cache-As-RAM */
96         jmp     car_init
97 .globl car_init_ret
98 car_init_ret:
99 #ifndef CONFIG_HAVE_FSP
100         /*
101          * We now have CONFIG_SYS_CAR_SIZE bytes of Cache-As-RAM (or SRAM,
102          * or fully initialised SDRAM - we really don't care which)
103          * starting at CONFIG_SYS_CAR_ADDR to be used as a temporary stack
104          * and early malloc() area. The MRC requires some space at the top.
105          *
106          * Stack grows down from top of CAR. We have:
107          *
108          * top-> CONFIG_SYS_CAR_ADDR + CONFIG_SYS_CAR_SIZE
109          *      MRC area
110          *      global_data with x86 global descriptor table
111          *      early malloc area
112          *      stack
113          * bottom-> CONFIG_SYS_CAR_ADDR
114          */
115         movl    $(CONFIG_SYS_CAR_ADDR + CONFIG_SYS_CAR_SIZE - 4), %esp
116 #ifdef CONFIG_DCACHE_RAM_MRC_VAR_SIZE
117         subl    $CONFIG_DCACHE_RAM_MRC_VAR_SIZE, %esp
118 #endif
119 #else
120         /*
121          * U-Boot enters here twice. For the first time it comes from
122          * car_init_done() with esp points to a temporary stack and esi
123          * set to zero. For the second time it comes from fsp_init_done()
124          * with esi holding the HOB list address returned by the FSP.
125          */
126 #endif
127         /* Set up global data */
128         mov     %esp, %eax
129         call    board_init_f_alloc_reserve
130         mov     %eax, %esp
131         call    board_init_f_init_reserve
132
133 #ifdef CONFIG_DEBUG_UART
134         call    debug_uart_init
135 #endif
136
137         /* Get address of global_data */
138         mov     %fs:0, %edx
139 #ifdef CONFIG_HAVE_FSP
140         /* Store the HOB list if we have one */
141         test    %esi, %esi
142         jz      skip_hob
143         movl    %esi, GD_HOB_LIST(%edx)
144
145         /*
146          * After fsp_init() returns, the stack has already been switched to a
147          * place within system memory as defined by CONFIG_FSP_TEMP_RAM_ADDR.
148          * Enlarge the size of malloc() pool before relocation since we have
149          * plenty of memory now.
150          */
151         subl    $CONFIG_FSP_SYS_MALLOC_F_LEN, %esp
152         movl    %esp, GD_MALLOC_BASE(%edx)
153 skip_hob:
154 #else
155         /* Store table pointer */
156         movl    %esi, GD_TABLE(%edx)
157 #endif
158         /* Store BIST */
159         movl    %ebp, GD_BIST(%edx)
160
161         /* Set parameter to board_init_f() to boot flags */
162         post_code(POST_START_DONE)
163         xorl    %eax, %eax
164
165         /* Enter, U-Boot! */
166         call    board_init_f
167
168         /* indicate (lack of) progress */
169         movw    $0x85, %ax
170         jmp     die
171
172 .globl board_init_f_r_trampoline
173 .type board_init_f_r_trampoline, @function
174 board_init_f_r_trampoline:
175         /*
176          * SDRAM has been initialised, U-Boot code has been copied into
177          * RAM, BSS has been cleared and relocation adjustments have been
178          * made. It is now time to jump into the in-RAM copy of U-Boot
179          *
180          * %eax = Address of top of new stack
181          */
182
183         /* Stack grows down from top of SDRAM */
184         movl    %eax, %esp
185
186         /* See if we need to disable CAR */
187 .weak   car_uninit
188         movl    $car_uninit, %eax
189         cmpl    $0, %eax
190         jz      1f
191
192         call    car_uninit
193 1:
194         /* Re-enter U-Boot by calling board_init_f_r() */
195         call    board_init_f_r
196
197 die:
198         hlt
199         jmp     die
200         hlt
201
202 blank_idt_ptr:
203         .word   0               /* limit */
204         .long   0               /* base */
205
206         .p2align        2       /* force 4-byte alignment */
207
208         /* Add a multiboot header so U-Boot can be loaded by GRUB2 */
209 multiboot_header:
210         /* magic */
211         .long   0x1badb002
212         /* flags */
213         .long   (1 << 16)
214         /* checksum */
215         .long   -0x1BADB002 - (1 << 16)
216         /* header addr */
217         .long   multiboot_header - _x86boot_start + CONFIG_SYS_TEXT_BASE
218         /* load addr */
219         .long   CONFIG_SYS_TEXT_BASE
220         /* load end addr */
221         .long   0
222         /* bss end addr */
223         .long   0
224         /* entry addr */
225         .long   CONFIG_SYS_TEXT_BASE
226
227 #ifdef CONFIG_X86_LOAD_FROM_32_BIT
228         /*
229          * The following Global Descriptor Table is just enough to get us into
230          * 'Flat Protected Mode' - It will be discarded as soon as the final
231          * GDT is setup in a safe location in RAM
232          */
233 gdt_ptr2:
234         .word   0x1f            /* limit (31 bytes = 4 GDT entries - 1) */
235         .long   gdt_rom2        /* base */
236
237         /* Some CPUs are picky about GDT alignment... */
238         .align  16
239 .globl gdt_rom2
240 gdt_rom2:
241         /*
242          * The GDT table ...
243          *
244          *       Selector       Type
245          *       0x00           NULL
246          *       0x08           Unused
247          *       0x10           32bit code
248          *       0x18           32bit data/stack
249          */
250         /* The NULL Desciptor - Mandatory */
251         .word   0x0000          /* limit_low */
252         .word   0x0000          /* base_low */
253         .byte   0x00            /* base_middle */
254         .byte   0x00            /* access */
255         .byte   0x00            /* flags + limit_high */
256         .byte   0x00            /* base_high */
257
258         /* Unused Desciptor - (matches Linux) */
259         .word   0x0000          /* limit_low */
260         .word   0x0000          /* base_low */
261         .byte   0x00            /* base_middle */
262         .byte   0x00            /* access */
263         .byte   0x00            /* flags + limit_high */
264         .byte   0x00            /* base_high */
265
266         /*
267          * The Code Segment Descriptor:
268          * - Base   = 0x00000000
269          * - Size   = 4GB
270          * - Access = Present, Ring 0, Exec (Code), Readable
271          * - Flags  = 4kB Granularity, 32-bit
272          */
273         .word   0xffff          /* limit_low */
274         .word   0x0000          /* base_low */
275         .byte   0x00            /* base_middle */
276         .byte   0x9b            /* access */
277         .byte   0xcf            /* flags + limit_high */
278         .byte   0x00            /* base_high */
279
280         /*
281          * The Data Segment Descriptor:
282          * - Base   = 0x00000000
283          * - Size   = 4GB
284          * - Access = Present, Ring 0, Non-Exec (Data), Writable
285          * - Flags  = 4kB Granularity, 32-bit
286          */
287         .word   0xffff          /* limit_low */
288         .word   0x0000          /* base_low */
289         .byte   0x00            /* base_middle */
290         .byte   0x93            /* access */
291         .byte   0xcf            /* flags + limit_high */
292         .byte   0x00            /* base_high */
293 #endif