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 /* 28fea25720SGraeme Russ * This is the fail safe 32-bit bootstrap entry point. The 29fea25720SGraeme Russ * following code is not executed from a cold-reset (actually, a 30fea25720SGraeme Russ * lot of it is, but from real-mode after cold reset. It is 31fea25720SGraeme Russ * repeated here to put the board into a state as close to cold 32fea25720SGraeme Russ * reset as necessary) 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 */ 4491d82a29SGabe Black movw $GD_FLG_WARM_BOOT, %bx 4591d82a29SGabe Black jmp 1f 46fea25720SGraeme Russ_start: 4791d82a29SGabe Black /* 4891d82a29SGabe Black * This is the 32-bit cold-reset entry point. Initialize %bx to 0 4991d82a29SGabe Black * in case we're preceeded by some sort of boot stub. 5091d82a29SGabe Black */ 5191d82a29SGabe Black movw $GD_FLG_COLD_BOOT, %bx 5291d82a29SGabe Black1: 53f67cd51eSSimon Glass /* Save BIST */ 54f67cd51eSSimon Glass movl %eax, %ebp 55fea25720SGraeme Russ 56fea25720SGraeme Russ /* Load the segement registes to match the gdt loaded in start16.S */ 57109ad143SGraeme Russ movl $(X86_GDT_ENTRY_32BIT_DS * X86_GDT_ENTRY_SIZE), %eax 58fea25720SGraeme Russ movw %ax, %fs 59fea25720SGraeme Russ movw %ax, %ds 60fea25720SGraeme Russ movw %ax, %gs 61fea25720SGraeme Russ movw %ax, %es 62fea25720SGraeme Russ movw %ax, %ss 63fea25720SGraeme Russ 6416263087SMike Williams /* Clear the interrupt vectors */ 65fea25720SGraeme Russ lidt blank_idt_ptr 66fea25720SGraeme Russ 67fea25720SGraeme Russ /* Early platform init (setup gpio, etc ) */ 68fea25720SGraeme Russ jmp early_board_init 69fea25720SGraeme Russ.globl early_board_init_ret 70fea25720SGraeme Russearly_board_init_ret: 71d1cd0459SSimon Glass post_code(POST_START) 72fea25720SGraeme Russ 73fea25720SGraeme Russ /* Initialise Cache-As-RAM */ 74fea25720SGraeme Russ jmp car_init 75fea25720SGraeme Russ.globl car_init_ret 76fea25720SGraeme Russcar_init_ret: 77bceb9f0fSBin Meng#ifndef CONFIG_HAVE_FSP 78fea25720SGraeme Russ /* 79fea25720SGraeme Russ * We now have CONFIG_SYS_CAR_SIZE bytes of Cache-As-RAM (or SRAM, 80fea25720SGraeme Russ * or fully initialised SDRAM - we really don't care which) 81fea25720SGraeme Russ * starting at CONFIG_SYS_CAR_ADDR to be used as a temporary stack 8265dd74a6SSimon Glass * and early malloc area. The MRC requires some space at the top. 8376f90f30SSimon Glass * 8476f90f30SSimon Glass * Stack grows down from top of CAR. We have: 8576f90f30SSimon Glass * 8676f90f30SSimon Glass * top-> CONFIG_SYS_CAR_ADDR + CONFIG_SYS_CAR_SIZE 8765dd74a6SSimon Glass * MRC area 8876f90f30SSimon Glass * global_data 8976f90f30SSimon Glass * x86 global descriptor table 9076f90f30SSimon Glass * early malloc area 9176f90f30SSimon Glass * stack 9276f90f30SSimon Glass * bottom-> CONFIG_SYS_CAR_ADDR 93fea25720SGraeme Russ */ 9465dd74a6SSimon Glass movl $(CONFIG_SYS_CAR_ADDR + CONFIG_SYS_CAR_SIZE - 4), %esp 9565dd74a6SSimon Glass#ifdef CONFIG_DCACHE_RAM_MRC_VAR_SIZE 9665dd74a6SSimon Glass subl $CONFIG_DCACHE_RAM_MRC_VAR_SIZE, %esp 9765dd74a6SSimon Glass#endif 98bceb9f0fSBin Meng#else 99bceb9f0fSBin Meng /* 100bceb9f0fSBin Meng * When we get here after car_init, esp points to a temporary stack 101bceb9f0fSBin Meng * and esi holds the HOB list address returned by the FSP. 102bceb9f0fSBin Meng */ 103bceb9f0fSBin Meng#endif 1048d61625dSGraeme Russ 1058d61625dSGraeme Russ /* Reserve space on stack for global data */ 1068d61625dSGraeme Russ subl $GENERATED_GBL_DATA_SIZE, %esp 1078d61625dSGraeme Russ 1088d61625dSGraeme Russ /* Align global data to 16-byte boundary */ 1098d61625dSGraeme Russ andl $0xfffffff0, %esp 110d1cd0459SSimon Glass post_code(POST_START_STACK) 1118d61625dSGraeme Russ 112fbd72824SSimon Glass /* Zero the global data since it won't happen later */ 113fbd72824SSimon Glass xorl %eax, %eax 114fbd72824SSimon Glass movl $GENERATED_GBL_DATA_SIZE, %ecx 115fbd72824SSimon Glass movl %esp, %edi 116fbd72824SSimon Glass rep stosb 117fbd72824SSimon Glass 118bceb9f0fSBin Meng#ifdef CONFIG_HAVE_FSP 119*aefaff8eSBin Meng test %esi, %esi 120*aefaff8eSBin Meng jz skip_hob 121*aefaff8eSBin Meng 122bceb9f0fSBin Meng /* Store HOB list */ 123bceb9f0fSBin Meng movl %esp, %edx 124bceb9f0fSBin Meng addl $GD_HOB_LIST, %edx 125bceb9f0fSBin Meng movl %esi, (%edx) 126bceb9f0fSBin Meng 127*aefaff8eSBin Mengskip_hob: 128*aefaff8eSBin Meng#endif 12976f90f30SSimon Glass /* Setup first parameter to setup_gdt, pointer to global_data */ 1308d61625dSGraeme Russ movl %esp, %eax 1318d61625dSGraeme Russ 1328d61625dSGraeme Russ /* Reserve space for global descriptor table */ 1338d61625dSGraeme Russ subl $X86_GDT_SIZE, %esp 1348d61625dSGraeme Russ 13576f90f30SSimon Glass /* Align temporary global descriptor table to 16-byte boundary */ 13676f90f30SSimon Glass andl $0xfffffff0, %esp 13776f90f30SSimon Glass movl %esp, %ecx 13876f90f30SSimon Glass 1395dbcaa21SSimon Glass#if defined(CONFIG_SYS_MALLOC_F_LEN) 1405dbcaa21SSimon Glass subl $CONFIG_SYS_MALLOC_F_LEN, %esp 1415dbcaa21SSimon Glass movl %eax, %edx 1425dbcaa21SSimon Glass addl $GD_MALLOC_BASE, %edx 1435dbcaa21SSimon Glass movl %esp, (%edx) 1445dbcaa21SSimon Glass#endif 145f67cd51eSSimon Glass /* Store BIST */ 146f67cd51eSSimon Glass movl %eax, %edx 147f67cd51eSSimon Glass addl $GD_BIST, %edx 148f67cd51eSSimon Glass movl %ebp, (%edx) 1498d61625dSGraeme Russ 1508d61625dSGraeme Russ /* Set second parameter to setup_gdt */ 15176f90f30SSimon Glass movl %ecx, %edx 1528d61625dSGraeme Russ 1538d61625dSGraeme Russ /* Setup global descriptor table so gd->xyz works */ 1548d61625dSGraeme Russ call setup_gdt 1559e6c572fSGraeme Russ 156fea25720SGraeme Russ /* Set parameter to board_init_f() to boot flags */ 157d1cd0459SSimon Glass post_code(POST_START_DONE) 158fea25720SGraeme Russ xorl %eax, %eax 159fea25720SGraeme Russ 160fea25720SGraeme Russ /* Enter, U-boot! */ 161fea25720SGraeme Russ call board_init_f 162fea25720SGraeme Russ 163fea25720SGraeme Russ /* indicate (lack of) progress */ 164fea25720SGraeme Russ movw $0x85, %ax 165fea25720SGraeme Russ jmp die 166fea25720SGraeme Russ 167f48dd6fcSGraeme Russ.globl board_init_f_r_trampoline 168f48dd6fcSGraeme Russ.type board_init_f_r_trampoline, @function 169f48dd6fcSGraeme Russboard_init_f_r_trampoline: 170fea25720SGraeme Russ /* 171fea25720SGraeme Russ * SDRAM has been initialised, U-Boot code has been copied into 172fea25720SGraeme Russ * RAM, BSS has been cleared and relocation adjustments have been 173fea25720SGraeme Russ * made. It is now time to jump into the in-RAM copy of U-Boot 174fea25720SGraeme Russ * 175f48dd6fcSGraeme Russ * %eax = Address of top of new stack 176fea25720SGraeme Russ */ 177fea25720SGraeme Russ 1788d61625dSGraeme Russ /* Stack grows down from top of SDRAM */ 179fea25720SGraeme Russ movl %eax, %esp 180fea25720SGraeme Russ 1818d61625dSGraeme Russ /* Reserve space on stack for global data */ 1828d61625dSGraeme Russ subl $GENERATED_GBL_DATA_SIZE, %esp 1838d61625dSGraeme Russ 1848d61625dSGraeme Russ /* Align global data to 16-byte boundary */ 1858d61625dSGraeme Russ andl $0xfffffff0, %esp 1868d61625dSGraeme Russ 1878d61625dSGraeme Russ /* Setup first parameter to memcpy (and setup_gdt) */ 1888d61625dSGraeme Russ movl %esp, %eax 1898d61625dSGraeme Russ 1908d61625dSGraeme Russ /* Setup second parameter to memcpy */ 1918d61625dSGraeme Russ fs movl 0, %edx 1928d61625dSGraeme Russ 1938d61625dSGraeme Russ /* Set third parameter to memcpy */ 1948d61625dSGraeme Russ movl $GENERATED_GBL_DATA_SIZE, %ecx 1958d61625dSGraeme Russ 1968d61625dSGraeme Russ /* Copy global data from CAR to SDRAM stack */ 1978d61625dSGraeme Russ call memcpy 1988d61625dSGraeme Russ 1998d61625dSGraeme Russ /* Reserve space for global descriptor table */ 2008d61625dSGraeme Russ subl $X86_GDT_SIZE, %esp 2018d61625dSGraeme Russ 2028d61625dSGraeme Russ /* Align global descriptor table to 16-byte boundary */ 2038d61625dSGraeme Russ andl $0xfffffff0, %esp 2048d61625dSGraeme Russ 2058d61625dSGraeme Russ /* Set second parameter to setup_gdt */ 2068d61625dSGraeme Russ movl %esp, %edx 2078d61625dSGraeme Russ 2088d61625dSGraeme Russ /* Setup global descriptor table so gd->xyz works */ 2098d61625dSGraeme Russ call setup_gdt 2108d61625dSGraeme Russ 211801d70ceSSimon Glass /* Set if we need to disable CAR */ 212801d70ceSSimon Glass.weak car_uninit 213801d70ceSSimon Glass movl $car_uninit, %eax 214801d70ceSSimon Glass cmpl $0, %eax 215801d70ceSSimon Glass jz 1f 216801d70ceSSimon Glass 217801d70ceSSimon Glass call car_uninit 218801d70ceSSimon Glass1: 219f48dd6fcSGraeme Russ /* Re-enter U-Boot by calling board_init_f_r */ 220f48dd6fcSGraeme Russ call board_init_f_r 221fea25720SGraeme Russ 2222f0e0cd2SGraeme Russdie: 2232f0e0cd2SGraeme Russ hlt 224fea25720SGraeme Russ jmp die 225fea25720SGraeme Russ hlt 226fea25720SGraeme Russ 227fea25720SGraeme Russblank_idt_ptr: 228fea25720SGraeme Russ .word 0 /* limit */ 229fea25720SGraeme Russ .long 0 /* base */ 230a206cc23SGraeme Russ 231a206cc23SGraeme Russ .p2align 2 /* force 4-byte alignment */ 232a206cc23SGraeme Russ 233a206cc23SGraeme Russmultiboot_header: 234a206cc23SGraeme Russ /* magic */ 235a206cc23SGraeme Russ .long 0x1BADB002 236a206cc23SGraeme Russ /* flags */ 237a206cc23SGraeme Russ .long (1 << 16) 238a206cc23SGraeme Russ /* checksum */ 239a206cc23SGraeme Russ .long -0x1BADB002 - (1 << 16) 240a206cc23SGraeme Russ /* header addr */ 241a206cc23SGraeme Russ .long multiboot_header - _x86boot_start + CONFIG_SYS_TEXT_BASE 242a206cc23SGraeme Russ /* load addr */ 243a206cc23SGraeme Russ .long CONFIG_SYS_TEXT_BASE 244a206cc23SGraeme Russ /* load end addr */ 245a206cc23SGraeme Russ .long 0 246a206cc23SGraeme Russ /* bss end addr */ 247a206cc23SGraeme Russ .long 0 248a206cc23SGraeme Russ /* entry addr */ 249a206cc23SGraeme Russ .long CONFIG_SYS_TEXT_BASE 250