x86: Update the comment about booting for FSP2
[pandora-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          * Instructions for FSP1, but not FSP2:
128          * U-Boot enters here twice. For the first time it comes from
129          * car_init_done() with esp points to a temporary stack and esi
130          * set to zero. For the second time it comes from fsp_init_done()
131          * with esi holding the HOB list address returned by the FSP.
132          */
133 #endif
134         /* Set up global data */
135         mov     %esp, %eax
136         call    board_init_f_alloc_reserve
137         mov     %eax, %esp
138         call    board_init_f_init_reserve
139
140 #ifdef CONFIG_DEBUG_UART
141         call    debug_uart_init
142 #endif
143
144         /* Get address of global_data */
145         mov     %fs:0, %edx
146 #if defined(CONFIG_USE_HOB) && !defined(CONFIG_USE_CAR)
147         /* Store the HOB list if we have one */
148         test    %esi, %esi
149         jz      skip_hob
150         movl    %esi, GD_HOB_LIST(%edx)
151
152 #ifdef CONFIG_HAVE_FSP
153         /*
154          * After fsp_init() returns, the stack has already been switched to a
155          * place within system memory as defined by CONFIG_FSP_TEMP_RAM_ADDR.
156          * Enlarge the size of malloc() pool before relocation since we have
157          * plenty of memory now.
158          */
159         subl    $CONFIG_FSP_SYS_MALLOC_F_LEN, %esp
160         movl    %esp, GD_MALLOC_BASE(%edx)
161 #endif
162 skip_hob:
163 #else
164         /* Store table pointer */
165         movl    %esi, GD_TABLE(%edx)
166 #endif
167         /* Store BIST */
168         movl    %ebp, GD_BIST(%edx)
169
170         /* Set parameter to board_init_f() to boot flags */
171         post_code(POST_START_DONE)
172         xorl    %eax, %eax
173
174         /* Enter, U-Boot! */
175         call    board_init_f
176
177         /* indicate (lack of) progress */
178         movw    $0x85, %ax
179         jmp     die
180
181 .globl board_init_f_r_trampoline
182 .type board_init_f_r_trampoline, @function
183 board_init_f_r_trampoline:
184         /*
185          * SDRAM has been initialised, U-Boot code has been copied into
186          * RAM, BSS has been cleared and relocation adjustments have been
187          * made. It is now time to jump into the in-RAM copy of U-Boot
188          *
189          * %eax = Address of top of new stack
190          */
191
192         /* Stack grows down from top of SDRAM */
193         movl    %eax, %esp
194
195         /* See if we need to disable CAR */
196         call    car_uninit
197
198         /* Re-enter U-Boot by calling board_init_f_r() */
199         call    board_init_f_r
200
201 #ifdef CONFIG_TPL
202 .globl jump_to_spl
203 .type jump_to_spl, @function
204 jump_to_spl:
205         /* Reset stack to the top of CAR space */
206         movl    $(CONFIG_SYS_CAR_ADDR + CONFIG_SYS_CAR_SIZE - 4), %esp
207 #ifdef CONFIG_DCACHE_RAM_MRC_VAR_SIZE
208         subl    $CONFIG_DCACHE_RAM_MRC_VAR_SIZE, %esp
209 #endif
210
211         jmp     *%eax
212 #endif
213
214 die:
215         hlt
216         jmp     die
217         hlt
218
219 WEAK(car_uninit)
220         ret
221 ENDPROC(car_uninit)
222
223 blank_idt_ptr:
224         .word   0               /* limit */
225         .long   0               /* base */
226
227         .p2align        2       /* force 4-byte alignment */
228
229         /* Add a multiboot header so U-Boot can be loaded by GRUB2 */
230 multiboot_header:
231         /* magic */
232         .long   0x1badb002
233         /* flags */
234         .long   (1 << 16)
235         /* checksum */
236         .long   -0x1BADB002 - (1 << 16)
237         /* header addr */
238         .long   multiboot_header - _x86boot_start + CONFIG_SYS_TEXT_BASE
239         /* load addr */
240         .long   CONFIG_SYS_TEXT_BASE
241         /* load end addr */
242         .long   0
243         /* bss end addr */
244         .long   0
245         /* entry addr */
246         .long   CONFIG_SYS_TEXT_BASE
247
248 #ifdef CONFIG_X86_LOAD_FROM_32_BIT
249         /*
250          * The following Global Descriptor Table is just enough to get us into
251          * 'Flat Protected Mode' - It will be discarded as soon as the final
252          * GDT is setup in a safe location in RAM
253          */
254 gdt_ptr2:
255         .word   0x1f            /* limit (31 bytes = 4 GDT entries - 1) */
256         .long   gdt_rom2        /* base */
257
258         /* Some CPUs are picky about GDT alignment... */
259         .align  16
260 .globl gdt_rom2
261 gdt_rom2:
262         /*
263          * The GDT table ...
264          *
265          *       Selector       Type
266          *       0x00           NULL
267          *       0x08           Unused
268          *       0x10           32bit code
269          *       0x18           32bit data/stack
270          */
271         /* The NULL Desciptor - Mandatory */
272         .word   0x0000          /* limit_low */
273         .word   0x0000          /* base_low */
274         .byte   0x00            /* base_middle */
275         .byte   0x00            /* access */
276         .byte   0x00            /* flags + limit_high */
277         .byte   0x00            /* base_high */
278
279         /* Unused Desciptor - (matches Linux) */
280         .word   0x0000          /* limit_low */
281         .word   0x0000          /* base_low */
282         .byte   0x00            /* base_middle */
283         .byte   0x00            /* access */
284         .byte   0x00            /* flags + limit_high */
285         .byte   0x00            /* base_high */
286
287         /*
288          * The Code Segment Descriptor:
289          * - Base   = 0x00000000
290          * - Size   = 4GB
291          * - Access = Present, Ring 0, Exec (Code), Readable
292          * - Flags  = 4kB Granularity, 32-bit
293          */
294         .word   0xffff          /* limit_low */
295         .word   0x0000          /* base_low */
296         .byte   0x00            /* base_middle */
297         .byte   0x9b            /* access */
298         .byte   0xcf            /* flags + limit_high */
299         .byte   0x00            /* base_high */
300
301         /*
302          * The Data Segment Descriptor:
303          * - Base   = 0x00000000
304          * - Size   = 4GB
305          * - Access = Present, Ring 0, Non-Exec (Data), Writable
306          * - Flags  = 4kB Granularity, 32-bit
307          */
308         .word   0xffff          /* limit_low */
309         .word   0x0000          /* base_low */
310         .byte   0x00            /* base_middle */
311         .byte   0x93            /* access */
312         .byte   0xcf            /* flags + limit_high */
313         .byte   0x00            /* base_high */
314 #endif