Changeset View
Standalone View
sys/boot/arm64/uboot/start.S
/*- | |||||
* Copyright (c) 2008 Semihalf, Rafal Czubak | |||||
* All rights reserved. | |||||
* | |||||
* Redistribution and use in source and binary forms, with or without | |||||
* modification, are permitted provided that the following conditions | |||||
* are met: | |||||
* 1. Redistributions of source code must retain the above copyright | |||||
* notice, this list of conditions and the following disclaimer. | |||||
* 2. Redistributions in binary form must reproduce the above copyright | |||||
* notice, this list of conditions and the following disclaimer in the | |||||
* documentation and/or other materials provided with the distribution. | |||||
* | |||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | |||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||||
* SUCH DAMAGE. | |||||
* | |||||
* $FreeBSD$ | |||||
*/ | |||||
#include <machine/asm.h> | |||||
#include <machine/armreg.h> | |||||
.text | |||||
.extern _C_LABEL(self_reloc), _C_LABEL(main) | |||||
.weak _DYNAMIC | |||||
/* | |||||
* Entry point to the loader that U-Boot passes control to. | |||||
*/ | |||||
.globl _start | |||||
_start: | |||||
/* | |||||
* Do self-relocation when the weak external symbol _DYNAMIC is non-NULL. | |||||
* When linked as a dynamic relocatable file, the linker automatically | |||||
* defines _DYNAMIC with a value that is the offset of the dynamic | |||||
* relocation info section. | |||||
* Note that we're still on u-boot's stack here, but the self_reloc | |||||
* code uses only a couple dozen bytes of stack space. | |||||
*/ | |||||
adr x15, .here_off | |||||
skibo: Sorry, destroyed this comment. Will fix. | |||||
ldr x0, [x15] /* is its own offset in the text seg. */ | |||||
sub x0, x15, x0 /* Get its pc-relative address and */ | |||||
ldr x1, .dynamic_off /* subtract its value and we get */ | |||||
cmp x1, #0 /* x0 = physaddr we were loaded at. */ | |||||
b.eq 2f | |||||
add x1, x1, x0 /* x1 = dynamic section physaddr. */ | |||||
bl _C_LABEL(self_reloc) /* Do reloc if _DYNAMIC is non-NULL. */ | |||||
2: | |||||
/* Hint where to look for the API signature */ | |||||
adr x15, uboot_address | |||||
mov x0, sp | |||||
str x0, [x15] | |||||
/* Save U-Boot's x18 */ | |||||
adr x15, saved_regs | |||||
str x18, [x15, #0] | |||||
/* | |||||
* Start loader. This is basically a tail-recursion call; if main() | |||||
* returns, it returns to u-boot (which reports the value returned x0). | |||||
*/ | |||||
b main | |||||
/* | |||||
* Data for self-relocation, in the text segment for pc-rel access. | |||||
*/ | |||||
.align 3 | |||||
.here_off: | |||||
.quad . | |||||
.dynamic_off: | |||||
.quad _DYNAMIC | |||||
skiboAuthorUnsubmitted Not Done Inline ActionsI can't get the position independent ubldr.pie to work because the linker leaves zeros in these locations. In the arm version, these locations are filled with offsets. Without the value of __DYNAMIC I don't know how to find the relocation data to pass to self_reloc(). skibo: I can't get the position independent ubldr.pie to work because the linker leaves zeros in these… | |||||
skiboAuthorUnsubmitted Not Done Inline ActionsOkay, I think I know what's going on. In aarch64, relocation data is stored in Elf64_Rela entries whereas arm uses Elf32_Rel entries (no addend field). In arm, the offsets go into the locations to be adjusted whereas in aarch64, the offsets go into the addend field in the entries in the relocation table and zeros go into locations that need to be adjusted. Any ideas how I could find the location of the dynamic section from within here so I can call self_reloc()? skibo: Okay, I think I know what's going on. In aarch64, relocation data is stored in Elf64_Rela… | |||||
andrewUnsubmitted Not Done Inline ActionsHave you looked at the efi code? It's a lot simpler than this, and has been tested on various hardware. andrew: Have you looked at the efi code? It's a lot simpler than this, and has been tested on various… | |||||
skiboAuthorUnsubmitted Not Done Inline ActionsThanks! I got it to work. So we should just build a relocatable ubldr only. skibo: Thanks! I got it to work. So we should just build a relocatable ubldr only. | |||||
/* | |||||
* syscall() | |||||
*/ | |||||
ENTRY(syscall) | |||||
/* Save caller's lr, x18 */ | |||||
adr x15, saved_regs | |||||
str x18, [x15, #8] | |||||
str lr, [x15, #16] | |||||
/* Restore U-Boot's x18 */ | |||||
ldr x18, saved_regs | |||||
/* Call into U-Boot */ | |||||
adr lr, return_from_syscall | |||||
ldr x15, syscall_ptr | |||||
br x15 | |||||
return_from_syscall: | |||||
/* Restore loader's x18 and lr */ | |||||
ldr lr, saved_regs + 16 | |||||
ldr x18, saved_regs + 8 | |||||
/* Return to caller */ | |||||
ret | |||||
/* | |||||
* Data section | |||||
*/ | |||||
.data | |||||
.align 3 | |||||
.globl syscall_ptr | |||||
syscall_ptr: | |||||
.quad 0 | |||||
.globl uboot_address | |||||
uboot_address: | |||||
.quad 0 | |||||
saved_regs: | |||||
.quad 0 /* U-Boot's x18 */ | |||||
.quad 0 /* Loader's x18 */ | |||||
.quad 0 /* Loader's lr */ |
Sorry, destroyed this comment. Will fix.