xref: /rk3399_rockchip-uboot/arch/x86/cpu/start.S (revision bbbe55f6f25e686ad799c2a70aa941eeb276adb6)
1fea25720SGraeme Russ/*
2fe0c33a5SBin Meng *  U-Boot - x86 Startup Code
3fea25720SGraeme Russ *
4fea25720SGraeme Russ * (C) Copyright 2008-2011
5fea25720SGraeme Russ * Graeme Russ, <graeme.russ@gmail.com>
6fea25720SGraeme Russ *
7fea25720SGraeme Russ * (C) Copyright 2002
8fa82f871SAlbert ARIBAUD * Daniel Engström, Omicron Ceti AB, <daniel@omicron.se>
9fea25720SGraeme Russ *
101a459660SWolfgang Denk * SPDX-License-Identifier:	GPL-2.0+
11fea25720SGraeme Russ */
12fea25720SGraeme Russ
13fea25720SGraeme Russ#include <config.h>
14fea25720SGraeme Russ#include <asm/global_data.h>
15d1cd0459SSimon Glass#include <asm/post.h>
16109ad143SGraeme Russ#include <asm/processor.h>
17fea25720SGraeme Russ#include <asm/processor-flags.h>
189e6c572fSGraeme Russ#include <generated/generic-asm-offsets.h>
19fe0c33a5SBin Meng#include <generated/asm-offsets.h>
20fea25720SGraeme Russ
21fea25720SGraeme Russ.section .text
22fea25720SGraeme Russ.code32
23fea25720SGraeme Russ.globl _start
24fea25720SGraeme Russ.type _start, @function
25fea25720SGraeme Russ.globl _x86boot_start
26fea25720SGraeme Russ_x86boot_start:
27fea25720SGraeme Russ	/*
28da3a95d6SSimon Glass	 * This is the fail-safe 32-bit bootstrap entry point.
29da3a95d6SSimon Glass	 *
30da3a95d6SSimon Glass	 * This code is used when booting from another boot loader like
31da3a95d6SSimon Glass	 * coreboot or EFI. So we repeat some of the same init found in
32da3a95d6SSimon Glass	 * start16.
33fea25720SGraeme Russ	 */
34fea25720SGraeme Russ	cli
35fea25720SGraeme Russ	cld
36fea25720SGraeme Russ
372f0e0cd2SGraeme Russ	/* Turn off cache (this might require a 486-class CPU) */
38fea25720SGraeme Russ	movl	%cr0, %eax
39fea25720SGraeme Russ	orl	$(X86_CR0_NW | X86_CR0_CD), %eax
40fea25720SGraeme Russ	movl	%eax, %cr0
41fea25720SGraeme Russ	wbinvd
42fea25720SGraeme Russ
4391d82a29SGabe Black	/* Tell 32-bit code it is being entered from an in-RAM copy */
4483ec7de3SSimon Glass	movl	$GD_FLG_WARM_BOOT, %ebx
4542fde305SSimon Glass
4642fde305SSimon Glass	/*
4742fde305SSimon Glass	 * Zero the BIST (Built-In Self Test) value since we don't have it.
4842fde305SSimon Glass	 * It must be 0 or the previous loader would have reported an error.
4942fde305SSimon Glass	 */
5042fde305SSimon Glass	movl	$0, %ebp
5142fde305SSimon Glass
5291d82a29SGabe Black	jmp	1f
5383ec7de3SSimon Glass
5483ec7de3SSimon Glass	/* Add a way for tools to discover the _start entry point */
5583ec7de3SSimon Glass	.align	4
5683ec7de3SSimon Glass	.long	0x12345678
57fea25720SGraeme Russ_start:
5891d82a29SGabe Black	/*
59da3a95d6SSimon Glass	 * This is the 32-bit cold-reset entry point, coming from start16.
6083ec7de3SSimon Glass	 * Set %ebx to GD_FLG_COLD_BOOT to indicate this.
6191d82a29SGabe Black	 */
6283ec7de3SSimon Glass	movl	$GD_FLG_COLD_BOOT, %ebx
6342fde305SSimon Glass
64f67cd51eSSimon Glass	/* Save BIST */
65f67cd51eSSimon Glass	movl	%eax, %ebp
6642fde305SSimon Glass1:
6742fde305SSimon Glass
6842fde305SSimon Glass	/* Save table pointer */
6942fde305SSimon Glass	movl	%ecx, %esi
70fea25720SGraeme Russ
71da3a95d6SSimon Glass	/* Load the segement registers to match the GDT loaded in start16.S */
72109ad143SGraeme Russ	movl	$(X86_GDT_ENTRY_32BIT_DS * X86_GDT_ENTRY_SIZE), %eax
73fea25720SGraeme Russ	movw	%ax, %fs
74fea25720SGraeme Russ	movw	%ax, %ds
75fea25720SGraeme Russ	movw	%ax, %gs
76fea25720SGraeme Russ	movw	%ax, %es
77fea25720SGraeme Russ	movw	%ax, %ss
78fea25720SGraeme Russ
7916263087SMike Williams	/* Clear the interrupt vectors */
80fea25720SGraeme Russ	lidt	blank_idt_ptr
81fea25720SGraeme Russ
82da3a95d6SSimon Glass	/*
83da3a95d6SSimon Glass	 * Critical early platform init - generally not used, we prefer init
84da3a95d6SSimon Glass	 * to happen later when we have a console, in case something goes
85da3a95d6SSimon Glass	 * wrong.
86da3a95d6SSimon Glass	 */
87fea25720SGraeme Russ	jmp	early_board_init
88fea25720SGraeme Russ.globl early_board_init_ret
89fea25720SGraeme Russearly_board_init_ret:
90d1cd0459SSimon Glass	post_code(POST_START)
91fea25720SGraeme Russ
92fea25720SGraeme Russ	/* Initialise Cache-As-RAM */
93fea25720SGraeme Russ	jmp	car_init
94fea25720SGraeme Russ.globl car_init_ret
95fea25720SGraeme Russcar_init_ret:
96bceb9f0fSBin Meng#ifndef CONFIG_HAVE_FSP
97fea25720SGraeme Russ	/*
98fea25720SGraeme Russ	 * We now have CONFIG_SYS_CAR_SIZE bytes of Cache-As-RAM (or SRAM,
99fea25720SGraeme Russ	 * or fully initialised SDRAM - we really don't care which)
100fea25720SGraeme Russ	 * starting at CONFIG_SYS_CAR_ADDR to be used as a temporary stack
101da3a95d6SSimon Glass	 * and early malloc() area. The MRC requires some space at the top.
10276f90f30SSimon Glass	 *
10376f90f30SSimon Glass	 * Stack grows down from top of CAR. We have:
10476f90f30SSimon Glass	 *
10576f90f30SSimon Glass	 * top-> CONFIG_SYS_CAR_ADDR + CONFIG_SYS_CAR_SIZE
10665dd74a6SSimon Glass	 *	MRC area
10776f90f30SSimon Glass	 *	global_data
10876f90f30SSimon Glass	 *	x86 global descriptor table
10976f90f30SSimon Glass	 *	early malloc area
11076f90f30SSimon Glass	 *	stack
11176f90f30SSimon Glass	 * bottom-> CONFIG_SYS_CAR_ADDR
112fea25720SGraeme Russ	 */
11365dd74a6SSimon Glass	movl	$(CONFIG_SYS_CAR_ADDR + CONFIG_SYS_CAR_SIZE - 4), %esp
11465dd74a6SSimon Glass#ifdef CONFIG_DCACHE_RAM_MRC_VAR_SIZE
11565dd74a6SSimon Glass	subl	$CONFIG_DCACHE_RAM_MRC_VAR_SIZE, %esp
11665dd74a6SSimon Glass#endif
117bceb9f0fSBin Meng#else
118bceb9f0fSBin Meng	/*
119da3a95d6SSimon Glass	 * When we get here after car_init(), esp points to a temporary stack
120bceb9f0fSBin Meng	 * and esi holds the HOB list address returned by the FSP.
121bceb9f0fSBin Meng	 */
122bceb9f0fSBin Meng#endif
1238d61625dSGraeme Russ
1248d61625dSGraeme Russ	/* Reserve space on stack for global data */
1258d61625dSGraeme Russ	subl	$GENERATED_GBL_DATA_SIZE, %esp
1268d61625dSGraeme Russ
1278d61625dSGraeme Russ	/* Align global data to 16-byte boundary */
1288d61625dSGraeme Russ	andl	$0xfffffff0, %esp
129d1cd0459SSimon Glass	post_code(POST_START_STACK)
1308d61625dSGraeme Russ
131*bbbe55f6SSimon Glass	/*
132*bbbe55f6SSimon Glass	 * Debug UART is available here although it may not be plumbed out
133*bbbe55f6SSimon Glass	 * to pins depending on the board. To use it:
134*bbbe55f6SSimon Glass	 *
135*bbbe55f6SSimon Glass	 * call  debug_uart_init
136*bbbe55f6SSimon Glass	 * mov   $'a', %eax
137*bbbe55f6SSimon Glass	 * call  printch
138*bbbe55f6SSimon Glass	 */
139*bbbe55f6SSimon Glass
140fbd72824SSimon Glass	/* Zero the global data since it won't happen later */
141fbd72824SSimon Glass	xorl	%eax, %eax
142fbd72824SSimon Glass	movl	$GENERATED_GBL_DATA_SIZE, %ecx
143fbd72824SSimon Glass	movl	%esp, %edi
144fbd72824SSimon Glass	rep	stosb
145fbd72824SSimon Glass
146bceb9f0fSBin Meng#ifdef CONFIG_HAVE_FSP
147aefaff8eSBin Meng	test	%esi, %esi
148aefaff8eSBin Meng	jz	skip_hob
149aefaff8eSBin Meng
150bceb9f0fSBin Meng	/* Store HOB list */
151bceb9f0fSBin Meng	movl	%esp, %edx
152bceb9f0fSBin Meng	addl	$GD_HOB_LIST, %edx
153bceb9f0fSBin Meng	movl	%esi, (%edx)
154bceb9f0fSBin Meng
155aefaff8eSBin Mengskip_hob:
15642fde305SSimon Glass#else
15742fde305SSimon Glass	/* Store table pointer */
15842fde305SSimon Glass	movl	%esp, %edx
15942fde305SSimon Glass	addl	$GD_TABLE, %edx
16042fde305SSimon Glass	movl	%esi, (%edx)
161aefaff8eSBin Meng#endif
16242fde305SSimon Glass
16376f90f30SSimon Glass	/* Setup first parameter to setup_gdt, pointer to global_data */
1648d61625dSGraeme Russ	movl	%esp, %eax
1658d61625dSGraeme Russ
1668d61625dSGraeme Russ	/* Reserve space for global descriptor table */
1678d61625dSGraeme Russ	subl	$X86_GDT_SIZE, %esp
1688d61625dSGraeme Russ
16976f90f30SSimon Glass	/* Align temporary global descriptor table to 16-byte boundary */
17076f90f30SSimon Glass	andl	$0xfffffff0, %esp
17176f90f30SSimon Glass	movl	%esp, %ecx
17276f90f30SSimon Glass
1735dbcaa21SSimon Glass#if defined(CONFIG_SYS_MALLOC_F_LEN)
174da3a95d6SSimon Glass	/* Set up the pre-relocation malloc pool */
1755dbcaa21SSimon Glass	subl	$CONFIG_SYS_MALLOC_F_LEN, %esp
1765dbcaa21SSimon Glass	movl	%eax, %edx
1775dbcaa21SSimon Glass	addl	$GD_MALLOC_BASE, %edx
1785dbcaa21SSimon Glass	movl	%esp, (%edx)
1795dbcaa21SSimon Glass#endif
180da3a95d6SSimon Glass	/* Store BIST into global_data */
181f67cd51eSSimon Glass	movl	%eax, %edx
182f67cd51eSSimon Glass	addl	$GD_BIST, %edx
183f67cd51eSSimon Glass	movl	%ebp, (%edx)
1848d61625dSGraeme Russ
185da3a95d6SSimon Glass	/* Set second parameter to setup_gdt() */
18676f90f30SSimon Glass	movl	%ecx, %edx
1878d61625dSGraeme Russ
1888d61625dSGraeme Russ	/* Setup global descriptor table so gd->xyz works */
1898d61625dSGraeme Russ	call	setup_gdt
1909e6c572fSGraeme Russ
191fea25720SGraeme Russ	/* Set parameter to board_init_f() to boot flags */
192d1cd0459SSimon Glass	post_code(POST_START_DONE)
193fea25720SGraeme Russ	xorl	%eax, %eax
194fea25720SGraeme Russ
195da3a95d6SSimon Glass	/* Enter, U-Boot! */
196fea25720SGraeme Russ	call	board_init_f
197fea25720SGraeme Russ
198fea25720SGraeme Russ	/* indicate (lack of) progress */
199fea25720SGraeme Russ	movw	$0x85, %ax
200fea25720SGraeme Russ	jmp	die
201fea25720SGraeme Russ
202f48dd6fcSGraeme Russ.globl board_init_f_r_trampoline
203f48dd6fcSGraeme Russ.type board_init_f_r_trampoline, @function
204f48dd6fcSGraeme Russboard_init_f_r_trampoline:
205fea25720SGraeme Russ	/*
206fea25720SGraeme Russ	 * SDRAM has been initialised, U-Boot code has been copied into
207fea25720SGraeme Russ	 * RAM, BSS has been cleared and relocation adjustments have been
208fea25720SGraeme Russ	 * made. It is now time to jump into the in-RAM copy of U-Boot
209fea25720SGraeme Russ	 *
210f48dd6fcSGraeme Russ	 * %eax = Address of top of new stack
211fea25720SGraeme Russ	 */
212fea25720SGraeme Russ
2138d61625dSGraeme Russ	/* Stack grows down from top of SDRAM */
214fea25720SGraeme Russ	movl	%eax, %esp
215fea25720SGraeme Russ
2168d61625dSGraeme Russ	/* Reserve space on stack for global data */
2178d61625dSGraeme Russ	subl	$GENERATED_GBL_DATA_SIZE, %esp
2188d61625dSGraeme Russ
2198d61625dSGraeme Russ	/* Align global data to 16-byte boundary */
2208d61625dSGraeme Russ	andl	$0xfffffff0, %esp
2218d61625dSGraeme Russ
222da3a95d6SSimon Glass	/* Setup first parameter to memcpy() and setup_gdt() */
2238d61625dSGraeme Russ	movl	%esp, %eax
2248d61625dSGraeme Russ
225da3a95d6SSimon Glass	/* Setup second parameter to memcpy() */
2268d61625dSGraeme Russ	fs movl 0, %edx
2278d61625dSGraeme Russ
228da3a95d6SSimon Glass	/* Set third parameter to memcpy() */
2298d61625dSGraeme Russ	movl	$GENERATED_GBL_DATA_SIZE, %ecx
2308d61625dSGraeme Russ
2318d61625dSGraeme Russ	/* Copy global data from CAR to SDRAM stack */
2328d61625dSGraeme Russ	call	memcpy
2338d61625dSGraeme Russ
2348d61625dSGraeme Russ	/* Reserve space for global descriptor table */
2358d61625dSGraeme Russ	subl	$X86_GDT_SIZE, %esp
2368d61625dSGraeme Russ
2378d61625dSGraeme Russ	/* Align global descriptor table to 16-byte boundary */
2388d61625dSGraeme Russ	andl	$0xfffffff0, %esp
2398d61625dSGraeme Russ
240da3a95d6SSimon Glass	/* Set second parameter to setup_gdt() */
2418d61625dSGraeme Russ	movl	%esp, %edx
2428d61625dSGraeme Russ
2438d61625dSGraeme Russ	/* Setup global descriptor table so gd->xyz works */
2448d61625dSGraeme Russ	call	setup_gdt
2458d61625dSGraeme Russ
246801d70ceSSimon Glass	/* Set if we need to disable CAR */
247801d70ceSSimon Glass.weak	car_uninit
248801d70ceSSimon Glass	movl	$car_uninit, %eax
249801d70ceSSimon Glass	cmpl	$0, %eax
250801d70ceSSimon Glass	jz	1f
251801d70ceSSimon Glass
252801d70ceSSimon Glass	call	car_uninit
253801d70ceSSimon Glass1:
254da3a95d6SSimon Glass	/* Re-enter U-Boot by calling board_init_f_r() */
255f48dd6fcSGraeme Russ	call	board_init_f_r
256fea25720SGraeme Russ
2572f0e0cd2SGraeme Russdie:
2582f0e0cd2SGraeme Russ	hlt
259fea25720SGraeme Russ	jmp	die
260fea25720SGraeme Russ	hlt
261fea25720SGraeme Russ
262fea25720SGraeme Russblank_idt_ptr:
263fea25720SGraeme Russ	.word	0		/* limit */
264fea25720SGraeme Russ	.long	0		/* base */
265a206cc23SGraeme Russ
266a206cc23SGraeme Russ	.p2align	2	/* force 4-byte alignment */
267a206cc23SGraeme Russ
268da3a95d6SSimon Glass	/* Add a multiboot header so U-Boot can be loaded by GRUB2 */
269a206cc23SGraeme Russmultiboot_header:
270a206cc23SGraeme Russ	/* magic */
271da3a95d6SSimon Glass	.long	0x1badb002
272a206cc23SGraeme Russ	/* flags */
273a206cc23SGraeme Russ	.long	(1 << 16)
274a206cc23SGraeme Russ	/* checksum */
275a206cc23SGraeme Russ	.long	-0x1BADB002 - (1 << 16)
276a206cc23SGraeme Russ	/* header addr */
277a206cc23SGraeme Russ	.long	multiboot_header - _x86boot_start + CONFIG_SYS_TEXT_BASE
278a206cc23SGraeme Russ	/* load addr */
279a206cc23SGraeme Russ	.long	CONFIG_SYS_TEXT_BASE
280a206cc23SGraeme Russ	/* load end addr */
281a206cc23SGraeme Russ	.long	0
282a206cc23SGraeme Russ	/* bss end addr */
283a206cc23SGraeme Russ	.long	0
284a206cc23SGraeme Russ	/* entry addr */
285a206cc23SGraeme Russ	.long	CONFIG_SYS_TEXT_BASE
286