Home | History | Annotate | Download | only in cpu
      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 (at) gmail.com>
      7  *
      8  * (C) Copyright 2002
      9  * Daniel Engstrm, Omicron Ceti AB, <daniel (at) 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
    294