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