summaryrefslogtreecommitdiffstats
path: root/sys/boot/arm/uboot/start.S
blob: 1ef21f3671f010f388bbf317c8f99134de968f95 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/*-
 * 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:

#ifdef _ARM_ARCH_6
	mrc     p15, 0, ip, c1, c0, 0
	orr	ip, ip, #(CPU_CONTROL_UNAL_ENABLE)
	orr	ip, ip, #(CPU_CONTROL_AFLT_ENABLE)
	mcr     p15, 0, ip, c1, c0, 0
#endif
	/* 
	 * 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	ip, .here_off		/* .here_off is a symbol whose value */
	ldr	r0, [ip]		/* is its own offset in the text seg. */
	sub	r0, ip, r0		/* Get its pc-relative address and */
	ldr	r1, .dynamic_off	/* subtract its value and we get */
	teq	r1, #0			/* r0 = physaddr we were loaded at. */
	addne	r1, r1, r0		/* r1 = dynamic section physaddr. */
	blne	_C_LABEL(self_reloc)	/* Do reloc if _DYNAMIC is non-NULL. */

	/* Hint where to look for the API signature */
	ldr	ip, =uboot_address
	str	sp, [ip]

	/* Save U-Boot's r8 and r9 */
	ldr	ip, =saved_regs
	str	r8, [ip, #0]
	str	r9, [ip, #4]

	/* 
	 * Start loader.  This is basically a tail-recursion call; if main()
	 * returns, it returns to u-boot (which reports the value returned r0).
	 */
	b	main

	/* 
	 * Data for self-relocation, in the text segment for pc-rel access.
	 */
.here_off:
	.word	.
.dynamic_off:
	.word	_DYNAMIC

/*
 * syscall()
 */
ENTRY(syscall)
	/* Save caller's lr, r8 and r9 */
	ldr	ip, =saved_regs
	str	r8, [ip, #8]
	str	r9, [ip, #12]
	str	lr, [ip, #16]
	/* Restore U-Boot's r8 and r9 */
	ldr	r8, [ip, #0]
	ldr	r9, [ip, #4]
	/* Call into U-Boot */
	ldr	lr, =return_from_syscall
	ldr	ip, =syscall_ptr
	ldr	pc, [ip]
return_from_syscall:
	/* Restore loader's r8, r9 and lr */
	ldr	ip, =saved_regs
	ldr	lr, [ip, #16]
	ldr	r9, [ip, #12]
	ldr	r8, [ip, #8]
	/* Return to caller */
	mov	pc, lr

/*
 * Data section
 */
	.data
	.align	4
	.globl	syscall_ptr
syscall_ptr:
	.long	0

	.globl	uboot_address
uboot_address:
	.long	0

saved_regs:
	.long	0	/* U-Boot's r8 */
	.long	0	/* U-Boot's r9 */
	.long	0	/* Loader's r8 */
	.long	0	/* Loader's r9 */
	.long	0	/* Loader's lr */
OpenPOWER on IntegriCloud