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