1*9dc70af8SWarner Losh/*- 2*9dc70af8SWarner Losh * Copyright (c) 2008 Semihalf, Rafal Czubak 3*9dc70af8SWarner Losh * All rights reserved. 4*9dc70af8SWarner Losh * 5*9dc70af8SWarner Losh * Redistribution and use in source and binary forms, with or without 6*9dc70af8SWarner Losh * modification, are permitted provided that the following conditions 7*9dc70af8SWarner Losh * are met: 8*9dc70af8SWarner Losh * 1. Redistributions of source code must retain the above copyright 9*9dc70af8SWarner Losh * notice, this list of conditions and the following disclaimer. 10*9dc70af8SWarner Losh * 2. Redistributions in binary form must reproduce the above copyright 11*9dc70af8SWarner Losh * notice, this list of conditions and the following disclaimer in the 12*9dc70af8SWarner Losh * documentation and/or other materials provided with the distribution. 13*9dc70af8SWarner Losh * 14*9dc70af8SWarner Losh * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15*9dc70af8SWarner Losh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16*9dc70af8SWarner Losh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17*9dc70af8SWarner Losh * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18*9dc70af8SWarner Losh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19*9dc70af8SWarner Losh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20*9dc70af8SWarner Losh * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21*9dc70af8SWarner Losh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22*9dc70af8SWarner Losh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23*9dc70af8SWarner Losh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24*9dc70af8SWarner Losh * SUCH DAMAGE. 25*9dc70af8SWarner Losh */ 26*9dc70af8SWarner Losh 27*9dc70af8SWarner Losh#include <machine/asm.h> 28*9dc70af8SWarner Losh#include <machine/armreg.h> 29*9dc70af8SWarner Losh 30*9dc70af8SWarner Losh .text 31*9dc70af8SWarner Losh .extern _C_LABEL(self_reloc), _C_LABEL(main) 32*9dc70af8SWarner Losh .weak _DYNAMIC 33*9dc70af8SWarner Losh 34*9dc70af8SWarner Losh/* 35*9dc70af8SWarner Losh * Entry point to the loader that U-Boot passes control to. 36*9dc70af8SWarner Losh */ 37*9dc70af8SWarner Losh .globl _start 38*9dc70af8SWarner Losh_start: 39*9dc70af8SWarner Losh 40*9dc70af8SWarner Losh mrc p15, 0, ip, c1, c0, 0 41*9dc70af8SWarner Losh orr ip, ip, #(CPU_CONTROL_UNAL_ENABLE) 42*9dc70af8SWarner Losh orr ip, ip, #(CPU_CONTROL_AFLT_ENABLE) 43*9dc70af8SWarner Losh mcr p15, 0, ip, c1, c0, 0 44*9dc70af8SWarner Losh 45*9dc70af8SWarner Losh /* Save the arguments and return register before calling self_reloc */ 46*9dc70af8SWarner Losh push {r0, r1, r9, lr} 47*9dc70af8SWarner Losh 48*9dc70af8SWarner Losh /* 49*9dc70af8SWarner Losh * Do self-relocation when the weak external symbol _DYNAMIC is non-NULL. 50*9dc70af8SWarner Losh * When linked as a dynamic relocatable file, the linker automatically 51*9dc70af8SWarner Losh * defines _DYNAMIC with a value that is the offset of the dynamic 52*9dc70af8SWarner Losh * relocation info section. 53*9dc70af8SWarner Losh * Note that we're still on u-boot's stack here, but the self_reloc 54*9dc70af8SWarner Losh * code uses only a couple dozen bytes of stack space. 55*9dc70af8SWarner Losh */ 56*9dc70af8SWarner Losh adr ip, .here_off /* .here_off is a symbol whose value */ 57*9dc70af8SWarner Losh ldr r0, [ip] /* is its own offset in the text seg. */ 58*9dc70af8SWarner Losh sub r0, ip, r0 /* Get its pc-relative address and */ 59*9dc70af8SWarner Losh ldr r1, .dynamic_off /* subtract its value and we get */ 60*9dc70af8SWarner Losh teq r1, #0 /* r0 = physaddr we were loaded at. */ 61*9dc70af8SWarner Losh addne r1, r1, r0 /* r1 = dynamic section physaddr. */ 62*9dc70af8SWarner Losh blne _C_LABEL(self_reloc) /* Do reloc if _DYNAMIC is non-NULL. */ 63*9dc70af8SWarner Losh 64*9dc70af8SWarner Losh /* Restore saved arguments */ 65*9dc70af8SWarner Losh pop {r0, r1, r9, lr} 66*9dc70af8SWarner Losh 67*9dc70af8SWarner Losh /* Hint where to look for the API signature */ 68*9dc70af8SWarner Losh ldr ip, =uboot_address 69*9dc70af8SWarner Losh str sp, [ip] 70*9dc70af8SWarner Losh 71*9dc70af8SWarner Losh /* Save U-Boot's r8 and r9 for syscall trampoline */ 72*9dc70af8SWarner Losh ldr ip, =saved_regs 73*9dc70af8SWarner Losh str r8, [ip, #0] /* old gd pointer (use to hold lr) */ 74*9dc70af8SWarner Losh str r9, [ip, #4] /* new gd pointer */ 75*9dc70af8SWarner Losh 76*9dc70af8SWarner Losh /* 77*9dc70af8SWarner Losh * Start loader. Save return address first (r8 is available from 78*9dc70af8SWarner Losh * trampoline save). 79*9dc70af8SWarner Losh */ 80*9dc70af8SWarner Losh mov r8, lr 81*9dc70af8SWarner Losh bl main 82*9dc70af8SWarner Losh mov lr, r8 83*9dc70af8SWarner Losh 84*9dc70af8SWarner Losh /* Restore U-Boot environment */ 85*9dc70af8SWarner Losh ldr ip, =saved_regs 86*9dc70af8SWarner Losh ldr r8, [ip, #0] 87*9dc70af8SWarner Losh ldr r9, [ip, #4] 88*9dc70af8SWarner Losh mov pc, lr 89*9dc70af8SWarner Losh 90*9dc70af8SWarner Losh /* 91*9dc70af8SWarner Losh * Data for self-relocation, in the text segment for pc-rel access. 92*9dc70af8SWarner Losh */ 93*9dc70af8SWarner Losh.here_off: 94*9dc70af8SWarner Losh .word . 95*9dc70af8SWarner Losh.dynamic_off: 96*9dc70af8SWarner Losh .word _DYNAMIC 97*9dc70af8SWarner Losh 98*9dc70af8SWarner Losh/* 99*9dc70af8SWarner Losh * syscall() 100*9dc70af8SWarner Losh */ 101*9dc70af8SWarner LoshENTRY(syscall) 102*9dc70af8SWarner Losh /* Save caller's lr, r8 and r9 */ 103*9dc70af8SWarner Losh ldr ip, =saved_regs 104*9dc70af8SWarner Losh str r8, [ip, #8] 105*9dc70af8SWarner Losh str r9, [ip, #12] 106*9dc70af8SWarner Losh str lr, [ip, #16] 107*9dc70af8SWarner Losh /* Restore U-Boot's r8 and r9 */ 108*9dc70af8SWarner Losh ldr r8, [ip, #0] 109*9dc70af8SWarner Losh ldr r9, [ip, #4] 110*9dc70af8SWarner Losh /* Call into U-Boot */ 111*9dc70af8SWarner Losh ldr lr, =return_from_syscall 112*9dc70af8SWarner Losh ldr ip, =syscall_ptr 113*9dc70af8SWarner Losh ldr pc, [ip] 114*9dc70af8SWarner Loshreturn_from_syscall: 115*9dc70af8SWarner Losh /* Restore loader's r8, r9 and lr */ 116*9dc70af8SWarner Losh ldr ip, =saved_regs 117*9dc70af8SWarner Losh ldr lr, [ip, #16] 118*9dc70af8SWarner Losh ldr r9, [ip, #12] 119*9dc70af8SWarner Losh ldr r8, [ip, #8] 120*9dc70af8SWarner Losh /* Return to caller */ 121*9dc70af8SWarner Losh mov pc, lr 122*9dc70af8SWarner Losh 123*9dc70af8SWarner Losh/* 124*9dc70af8SWarner Losh * Data section 125*9dc70af8SWarner Losh */ 126*9dc70af8SWarner Losh .data 127*9dc70af8SWarner Losh .align 4 128*9dc70af8SWarner Losh .globl syscall_ptr 129*9dc70af8SWarner Loshsyscall_ptr: 130*9dc70af8SWarner Losh .long 0 131*9dc70af8SWarner Losh 132*9dc70af8SWarner Losh .globl uboot_address 133*9dc70af8SWarner Loshuboot_address: 134*9dc70af8SWarner Losh .long 0 135*9dc70af8SWarner Losh 136*9dc70af8SWarner Loshsaved_regs: 137*9dc70af8SWarner Losh .long 0 /* U-Boot's r8 */ 138*9dc70af8SWarner Losh .long 0 /* U-Boot's r9 */ 139*9dc70af8SWarner Losh .long 0 /* Loader's r8 */ 140*9dc70af8SWarner Losh .long 0 /* Loader's r9 */ 141*9dc70af8SWarner Losh .long 0 /* Loader's lr */ 142