aboutsummaryrefslogtreecommitdiff
path: root/rtas/reloc.S
blob: e24d293d42c165d4945715e500e11a81add2c34d (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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
/******************************************************************************
 * Copyright (c) 2004, 2008 IBM Corporation
 * All rights reserved.
 * This program and the accompanying materials
 * are made available under the terms of the BSD License
 * which accompanies this distribution, and is available at
 * http://www.opensource.org/licenses/bsd-license.php
 *
 * Contributors:
 *     IBM Corporation - initial implementation
 *****************************************************************************/

#include <rtas.h>		
			
/*
Function:	
	Input:
		r3:   Destination to copy rtas code to
		r4:   Configuration	
	Output:		
		r3:   Entry point for rtas calls	
Decription: Called by OpenFirmware to instantiate rtas, needs to copy
	itself to destination, also do a relocations.
	
*/

.extern	rtas_entry
.extern .stack
.extern _got
.extern _got_end
.extern __bss_start
.extern __bss_end
.extern rtas_config


	.section        ".rtasstart","ax";
	.align	3
	.globl _rtas_start
_rtas_start:
	mflr	r10		# save link register
	bcl	20,31,.over	# branch (always) to .over 

.base:
	.align  3

/* Our Open Firmware needs to know the size of the RTAS binary and the
 * size & address of the RTAS function jump table. SLOF always looks for this
 * information in the following three quads here at the very beginning of the
 * RTAS binary at offset 8. So DO NOT DELETE/MOVE them! */

._rtas_size:		.quad	_rtas_end-_rtas_start
._ptr_to_func_tab:	.quad	rtas_func_tab-_rtas_start
._ptr_to_func_tab_size:	.quad	rtas_func_tab_size-_rtas_start

/* The other variables are not accessed by SLOF anymore: */

._rel_offset:		.quad   _reloc_table_start-_rtas_start
._rel_end_offset:	.quad   _reloc_table_end-_rtas_start
._bss_offset:		.quad   __bss_start-_rtas_start
._bss_end_offset:	.quad   __bss_end-_rtas_start
._rtas_entry_offset:	.quad   rtas_entry-_rtas_start
._rtas_config_offset:	.quad   rtas_config-_rtas_start
._rtas_stack:	        .quad   .stack-_rtas_start+RTAS_STACKSIZE-0x60
._rtas_toc:	        .quad   _got-_rtas_start+0x8000

.over:	
	mflr r8			# gpr 8 is the base
	addi r8,r8,_rtas_start-.base # points to _rtas_start
	mr r11,r4		# Save config value	
	
# Copy rtas code
	
	ld r5,._rtas_size-_rtas_start(r8) 
	mr r4,r8		# Start of rtas
	addi r6,r3,-8		# Destination
	addi r4,r4,-8		# Source
	srdi r5,r5,3		# Count in quads
	mtctr r5
0:				
	ldu r0,8(r4)		
	stdu r0,8(r6)
	bdnz 0b		

# Clear bss

	ld r4,._bss_offset-_rtas_start(r8)
	ld r5,._bss_end_offset-_rtas_start(r8)
	li r0,0
	add r6,r3,r4		# Address bss in copied code
	addi r6,r6,-8
	sub r5,r5,r4		# Calculate bss size
	srdi r5,r5,3		# Count in quads
	mtctr r5	
0:	
	stdu r0,8(r6)
	bdnz 0b

# Relocate got

	ld	r4, ._rel_offset-_rtas_start(r8)
	ld	r5, ._rel_end_offset-_rtas_start(r8)
	sub	r5, r5,r4	# Calculate reloc table size
	cmpdi	r5, 0		# No reloc table ?
	beq	1f

	add	r4, r4, r3	# Calculate reloc table address
	addi	r4, r4, -4
	srdi	r5, r5, 2	# Count in words	
	mtctr	r5
0:	
	lwzu	r6, 4(r4)	# Load offset out of reloc table
	ldx	r0, r6, r3	# Load value 	
	add	r0, r0, r3	# Add relocation offset = load address
	stdx	r0, r6, r3
	bdnz	0b		
1:			

# Save config data

	ld r5,._rtas_config_offset-_rtas_start(r8)
	add r5,r5,r3
	std r11,0(r5)
	
# Flush to memory
	
	mr r4,r3		# Destination address
	ld r5,._rtas_size-_rtas_start(r8) 
		
	add r5,r5,r4
	addi r5,r5,127
	rlwinm r4,r4,0,0,24
	rlwinm r5,r5,0,0,24
	sub r5,r5,r4
	srwi r5,r5,7
	mtctr r5
0:
	dcbst 0,r4
	sync
	icbi 0,r4
	sync
	isync
	addi r4,r4,128
	bdnz 0b

# Call init function
	mfmsr	r11			# Switch to 64 bit mode
	mr	r7,r11
	rotldi	r11,r11,1
	ori	r11,r11,1
	rotldi	r11,r11,63
	mtmsrd	r11
	isync
	mr	r9,r1			# save old stack pointer
	ld	r1,._rtas_stack-_rtas_start(r8)	# load new stack pointer
	add	r1,r1,r3
	std	r9,0(r1)		# save stack pointer
	std	r2,64(r1)		# save toc
	std	r7,72(r1)		# save old msr value

	ld	r2,._rtas_toc-_rtas_start(r8)	# load got pointer
	add	r2,r2,r3

	bl	save_regs_r3_r12
	bl	.rtas_init
	bl	restore_regs_r3_r12

	ld	r11,72(r1)		# restore msr value	
	ld	r2,64(r1)		# restore toc
	ld	r1,0(r1)		# get old stack

	mtmsrd	r11			# restore msr
	isync


# Return rtas entry

	ld r4,._rtas_entry_offset-_rtas_start(r8)
	add r3,r3,r4
	mtlr	r10
	blr