1fea25720SGraeme Russ/* 2fea25720SGraeme Russ * 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 <version.h> 15fea25720SGraeme Russ#include <asm/global_data.h> 16109ad143SGraeme Russ#include <asm/processor.h> 17fea25720SGraeme Russ#include <asm/processor-flags.h> 189e6c572fSGraeme Russ#include <generated/generic-asm-offsets.h> 19fea25720SGraeme Russ 20fea25720SGraeme Russ.section .text 21fea25720SGraeme Russ.code32 22fea25720SGraeme Russ.globl _start 23fea25720SGraeme Russ.type _start, @function 24fea25720SGraeme Russ.globl _x86boot_start 25fea25720SGraeme Russ_x86boot_start: 26fea25720SGraeme Russ /* 27fea25720SGraeme Russ * This is the fail safe 32-bit bootstrap entry point. The 28fea25720SGraeme Russ * following code is not executed from a cold-reset (actually, a 29fea25720SGraeme Russ * lot of it is, but from real-mode after cold reset. It is 30fea25720SGraeme Russ * repeated here to put the board into a state as close to cold 31fea25720SGraeme Russ * reset as necessary) 32fea25720SGraeme Russ */ 33fea25720SGraeme Russ cli 34fea25720SGraeme Russ cld 35fea25720SGraeme Russ 362f0e0cd2SGraeme Russ /* Turn off cache (this might require a 486-class CPU) */ 37fea25720SGraeme Russ movl %cr0, %eax 38fea25720SGraeme Russ orl $(X86_CR0_NW | X86_CR0_CD), %eax 39fea25720SGraeme Russ movl %eax, %cr0 40fea25720SGraeme Russ wbinvd 41fea25720SGraeme Russ 4291d82a29SGabe Black /* Tell 32-bit code it is being entered from an in-RAM copy */ 4391d82a29SGabe Black movw $GD_FLG_WARM_BOOT, %bx 4491d82a29SGabe Black jmp 1f 45fea25720SGraeme Russ_start: 4691d82a29SGabe Black /* 4791d82a29SGabe Black * This is the 32-bit cold-reset entry point. Initialize %bx to 0 4891d82a29SGabe Black * in case we're preceeded by some sort of boot stub. 4991d82a29SGabe Black */ 5091d82a29SGabe Black movw $GD_FLG_COLD_BOOT, %bx 5191d82a29SGabe Black1: 52fea25720SGraeme Russ 53fea25720SGraeme Russ /* Load the segement registes to match the gdt loaded in start16.S */ 54109ad143SGraeme Russ movl $(X86_GDT_ENTRY_32BIT_DS * X86_GDT_ENTRY_SIZE), %eax 55fea25720SGraeme Russ movw %ax, %fs 56fea25720SGraeme Russ movw %ax, %ds 57fea25720SGraeme Russ movw %ax, %gs 58fea25720SGraeme Russ movw %ax, %es 59fea25720SGraeme Russ movw %ax, %ss 60fea25720SGraeme Russ 6116263087SMike Williams /* Clear the interrupt vectors */ 62fea25720SGraeme Russ lidt blank_idt_ptr 63fea25720SGraeme Russ 64fea25720SGraeme Russ /* Early platform init (setup gpio, etc ) */ 65fea25720SGraeme Russ jmp early_board_init 66fea25720SGraeme Russ.globl early_board_init_ret 67fea25720SGraeme Russearly_board_init_ret: 68fea25720SGraeme Russ 69fea25720SGraeme Russ /* Initialise Cache-As-RAM */ 70fea25720SGraeme Russ jmp car_init 71fea25720SGraeme Russ.globl car_init_ret 72fea25720SGraeme Russcar_init_ret: 73fea25720SGraeme Russ /* 74fea25720SGraeme Russ * We now have CONFIG_SYS_CAR_SIZE bytes of Cache-As-RAM (or SRAM, 75fea25720SGraeme Russ * or fully initialised SDRAM - we really don't care which) 76fea25720SGraeme Russ * starting at CONFIG_SYS_CAR_ADDR to be used as a temporary stack 77*76f90f30SSimon Glass * and early malloc area. 78*76f90f30SSimon Glass * 79*76f90f30SSimon Glass * Stack grows down from top of CAR. We have: 80*76f90f30SSimon Glass * 81*76f90f30SSimon Glass * top-> CONFIG_SYS_CAR_ADDR + CONFIG_SYS_CAR_SIZE 82*76f90f30SSimon Glass * global_data 83*76f90f30SSimon Glass * x86 global descriptor table 84*76f90f30SSimon Glass * early malloc area 85*76f90f30SSimon Glass * stack 86*76f90f30SSimon Glass * bottom-> CONFIG_SYS_CAR_ADDR 87fea25720SGraeme Russ */ 88fea25720SGraeme Russ 898d61625dSGraeme Russ /* Stack grows down from top of CAR */ 908d61625dSGraeme Russ movl $(CONFIG_SYS_CAR_ADDR + CONFIG_SYS_CAR_SIZE), %esp 918d61625dSGraeme Russ 928d61625dSGraeme Russ /* Reserve space on stack for global data */ 938d61625dSGraeme Russ subl $GENERATED_GBL_DATA_SIZE, %esp 948d61625dSGraeme Russ 958d61625dSGraeme Russ /* Align global data to 16-byte boundary */ 968d61625dSGraeme Russ andl $0xfffffff0, %esp 978d61625dSGraeme Russ 98fbd72824SSimon Glass /* Zero the global data since it won't happen later */ 99fbd72824SSimon Glass xorl %eax, %eax 100fbd72824SSimon Glass movl $GENERATED_GBL_DATA_SIZE, %ecx 101fbd72824SSimon Glass movl %esp, %edi 102fbd72824SSimon Glass rep stosb 103fbd72824SSimon Glass 104*76f90f30SSimon Glass /* Setup first parameter to setup_gdt, pointer to global_data */ 1058d61625dSGraeme Russ movl %esp, %eax 1068d61625dSGraeme Russ 1078d61625dSGraeme Russ /* Reserve space for global descriptor table */ 1088d61625dSGraeme Russ subl $X86_GDT_SIZE, %esp 1098d61625dSGraeme Russ 110*76f90f30SSimon Glass /* Align temporary global descriptor table to 16-byte boundary */ 111*76f90f30SSimon Glass andl $0xfffffff0, %esp 112*76f90f30SSimon Glass movl %esp, %ecx 113*76f90f30SSimon Glass 1145dbcaa21SSimon Glass#if defined(CONFIG_SYS_MALLOC_F_LEN) 1155dbcaa21SSimon Glass subl $CONFIG_SYS_MALLOC_F_LEN, %esp 1165dbcaa21SSimon Glass movl %eax, %edx 1175dbcaa21SSimon Glass addl $GD_MALLOC_BASE, %edx 1185dbcaa21SSimon Glass movl %esp, (%edx) 1195dbcaa21SSimon Glass#endif 1205dbcaa21SSimon Glass 1218d61625dSGraeme Russ /* Align temporary global descriptor table to 16-byte boundary */ 1228d61625dSGraeme Russ andl $0xfffffff0, %esp 1238d61625dSGraeme Russ 1248d61625dSGraeme Russ /* Set second parameter to setup_gdt */ 125*76f90f30SSimon Glass movl %ecx, %edx 1268d61625dSGraeme Russ 1278d61625dSGraeme Russ /* Setup global descriptor table so gd->xyz works */ 1288d61625dSGraeme Russ call setup_gdt 1299e6c572fSGraeme Russ 130fea25720SGraeme Russ /* Set parameter to board_init_f() to boot flags */ 131fea25720SGraeme Russ xorl %eax, %eax 132fea25720SGraeme Russ 133fea25720SGraeme Russ /* Enter, U-boot! */ 134fea25720SGraeme Russ call board_init_f 135fea25720SGraeme Russ 136fea25720SGraeme Russ /* indicate (lack of) progress */ 137fea25720SGraeme Russ movw $0x85, %ax 138fea25720SGraeme Russ jmp die 139fea25720SGraeme Russ 140f48dd6fcSGraeme Russ.globl board_init_f_r_trampoline 141f48dd6fcSGraeme Russ.type board_init_f_r_trampoline, @function 142f48dd6fcSGraeme Russboard_init_f_r_trampoline: 143fea25720SGraeme Russ /* 144fea25720SGraeme Russ * SDRAM has been initialised, U-Boot code has been copied into 145fea25720SGraeme Russ * RAM, BSS has been cleared and relocation adjustments have been 146fea25720SGraeme Russ * made. It is now time to jump into the in-RAM copy of U-Boot 147fea25720SGraeme Russ * 148f48dd6fcSGraeme Russ * %eax = Address of top of new stack 149fea25720SGraeme Russ */ 150fea25720SGraeme Russ 1518d61625dSGraeme Russ /* Stack grows down from top of SDRAM */ 152fea25720SGraeme Russ movl %eax, %esp 153fea25720SGraeme Russ 1548d61625dSGraeme Russ /* Reserve space on stack for global data */ 1558d61625dSGraeme Russ subl $GENERATED_GBL_DATA_SIZE, %esp 1568d61625dSGraeme Russ 1578d61625dSGraeme Russ /* Align global data to 16-byte boundary */ 1588d61625dSGraeme Russ andl $0xfffffff0, %esp 1598d61625dSGraeme Russ 1608d61625dSGraeme Russ /* Setup first parameter to memcpy (and setup_gdt) */ 1618d61625dSGraeme Russ movl %esp, %eax 1628d61625dSGraeme Russ 1638d61625dSGraeme Russ /* Setup second parameter to memcpy */ 1648d61625dSGraeme Russ fs movl 0, %edx 1658d61625dSGraeme Russ 1668d61625dSGraeme Russ /* Set third parameter to memcpy */ 1678d61625dSGraeme Russ movl $GENERATED_GBL_DATA_SIZE, %ecx 1688d61625dSGraeme Russ 1698d61625dSGraeme Russ /* Copy global data from CAR to SDRAM stack */ 1708d61625dSGraeme Russ call memcpy 1718d61625dSGraeme Russ 1728d61625dSGraeme Russ /* Reserve space for global descriptor table */ 1738d61625dSGraeme Russ subl $X86_GDT_SIZE, %esp 1748d61625dSGraeme Russ 1758d61625dSGraeme Russ /* Align global descriptor table to 16-byte boundary */ 1768d61625dSGraeme Russ andl $0xfffffff0, %esp 1778d61625dSGraeme Russ 1788d61625dSGraeme Russ /* Set second parameter to setup_gdt */ 1798d61625dSGraeme Russ movl %esp, %edx 1808d61625dSGraeme Russ 1818d61625dSGraeme Russ /* Setup global descriptor table so gd->xyz works */ 1828d61625dSGraeme Russ call setup_gdt 1838d61625dSGraeme Russ 184f48dd6fcSGraeme Russ /* Re-enter U-Boot by calling board_init_f_r */ 185f48dd6fcSGraeme Russ call board_init_f_r 186fea25720SGraeme Russ 1872f0e0cd2SGraeme Russdie: 1882f0e0cd2SGraeme Russ hlt 189fea25720SGraeme Russ jmp die 190fea25720SGraeme Russ hlt 191fea25720SGraeme Russ 192fea25720SGraeme Russblank_idt_ptr: 193fea25720SGraeme Russ .word 0 /* limit */ 194fea25720SGraeme Russ .long 0 /* base */ 195a206cc23SGraeme Russ 196a206cc23SGraeme Russ .p2align 2 /* force 4-byte alignment */ 197a206cc23SGraeme Russ 198a206cc23SGraeme Russmultiboot_header: 199a206cc23SGraeme Russ /* magic */ 200a206cc23SGraeme Russ .long 0x1BADB002 201a206cc23SGraeme Russ /* flags */ 202a206cc23SGraeme Russ .long (1 << 16) 203a206cc23SGraeme Russ /* checksum */ 204a206cc23SGraeme Russ .long -0x1BADB002 - (1 << 16) 205a206cc23SGraeme Russ /* header addr */ 206a206cc23SGraeme Russ .long multiboot_header - _x86boot_start + CONFIG_SYS_TEXT_BASE 207a206cc23SGraeme Russ /* load addr */ 208a206cc23SGraeme Russ .long CONFIG_SYS_TEXT_BASE 209a206cc23SGraeme Russ /* load end addr */ 210a206cc23SGraeme Russ .long 0 211a206cc23SGraeme Russ /* bss end addr */ 212a206cc23SGraeme Russ .long 0 213a206cc23SGraeme Russ /* entry addr */ 214a206cc23SGraeme Russ .long CONFIG_SYS_TEXT_BASE 215