[PATCH] powerpc: trivial: modify comments to refer to new location of files
[linux-2.6-block.git] / arch / ppc / boot / simple / relocate.S
CommitLineData
1da177e4 1/*
1da177e4
LT
2 * This is the common part of the loader relocation and initialization
3 * process. All of the board/processor specific initialization is
4 * done before we get here.
5 *
6 * Author: Tom Rini
7 * trini@mvista.com
8 * Derived from arch/ppc/boot/prep/head.S (Cort Dougan, many others).
9 *
10 * 2001-2004 (c) MontaVista, Software, Inc. This file is licensed under
11 * the terms of the GNU General Public License version 2. This program
12 * is licensed "as is" without any warranty of any kind, whether express
13 * or implied.
14 */
15
16#include <linux/config.h>
17#include <asm/cache.h>
18#include <asm/ppc_asm.h>
19
20#define GETSYM(reg, sym) \
21 lis reg, sym@h; ori reg, reg, sym@l
22
23 .text
24 /* We get called from the early initialization code.
25 * Register 3 has the address where we were loaded,
26 * Register 4 contains any residual data passed from the
27 * boot rom.
28 */
29 .globl relocate
30relocate:
31 /* Save r3, r4 for later.
32 * The r8/r11 are legacy registers so I don't have to
33 * rewrite the code below :-).
34 */
35 mr r8, r3
36 mr r11, r4
37
38 /* compute the size of the whole image in words. */
39 GETSYM(r4,start)
40 GETSYM(r5,end)
41
42 addi r5,r5,3 /* round up */
43 sub r5,r5,r4 /* end - start */
44 srwi r5,r5,2
45 mr r7,r5 /* Save for later use. */
46
47 /*
48 * Check if we need to relocate ourselves to the link addr or were
49 * we loaded there to begin with.
50 */
51 cmpw cr0,r3,r4
52 beq start_ldr /* If 0, we don't need to relocate */
53
54 /* Move this code somewhere safe. This is max(load + size, end)
55 * r8 == load address
56 */
57 GETSYM(r4, start)
58 GETSYM(r5, end)
59
60 sub r6,r5,r4
61 add r6,r8,r6 /* r6 == phys(load + size) */
62
63 cmpw r5,r6
64 bgt 1f
65 b 2f
661:
67 mr r6, r5
682:
69 /* dest is in r6 */
70 /* Ensure alignment --- this code is precautionary */
71 addi r6,r6,4
72 li r5,0x0003
73 andc r6,r6,r5
74
75 /* Find physical address and size of do_relocate */
76 GETSYM(r5, __relocate_start)
77 GETSYM(r4, __relocate_end)
78 GETSYM(r3, start)
79
80 /* Size to copy */
81 sub r4,r4,r5
82 srwi r4,r4,2
83
84 /* Src addr to copy (= __relocate_start - start + where_loaded) */
85 sub r3,r5,r3
86 add r5,r8,r3
87
88 /* Save dest */
89 mr r3, r6
90
91 /* Do the copy */
92 mtctr r4
933: lwz r4,0(r5)
94 stw r4,0(r3)
95 addi r3,r3,4
96 addi r5,r5,4
97 bdnz 3b
98
99 GETSYM(r4, __relocate_start)
100 GETSYM(r5, do_relocate)
101
102 sub r4,r5,r4 /* Get entry point for do_relocate in */
103 add r6,r6,r4 /* relocated section */
104
105 /* This will return to the relocated do_relocate */
106 mtlr r6
107 b flush_instruction_cache
108
109 .section ".relocate_code","xa"
110
111do_relocate:
112 /* We have 2 cases --- start < load, or start > load
113 * This determines whether we copy from the end, or the start.
114 * Its easier to have 2 loops than to have paramaterised
115 * loops. Sigh.
116 */
117 li r6,0 /* Clear checksum */
118 mtctr r7 /* Setup for a loop */
119
120 GETSYM(r4, start)
121 mr r3,r8 /* Get the load addr */
122
123 cmpw cr0,r4,r3 /* If we need to copy from the end, do so */
124 bgt do_relocate_from_end
125
126do_relocate_from_start:
1271: lwz r5,0(r3) /* Load and decrement */
128 stw r5,0(r4) /* Store and decrement */
129 addi r3,r3,4
130 addi r4,r4,4
131 xor r6,r6,r5 /* Update checksum */
132 bdnz 1b /* Are we done? */
133 b do_relocate_out /* Finished */
134
135do_relocate_from_end:
136 GETSYM(r3, end)
137 slwi r4,r7,2
138 add r4,r8,r4 /* Get the physical end */
1391: lwzu r5,-4(r4)
140 stwu r5, -4(r3)
141 xor r6,r6,r5
142 bdnz 1b
143
144do_relocate_out:
145 GETSYM(r3,start_ldr)
146 mtlr r3 /* Easiest way to do an absolute jump */
147/* Some boards don't boot up with the I-cache enabled. Do that
148 * now because the decompress runs much faster that way.
149 * As a side effect, we have to ensure the data cache is not enabled
150 * so we can access the serial I/O without trouble.
151 */
152 b flush_instruction_cache
153
154 .previous
155
156start_ldr:
157/* Clear all of BSS and set up stack for C calls */
158 lis r3,edata@h
159 ori r3,r3,edata@l
160 lis r4,end@h
161 ori r4,r4,end@l
162 subi r3,r3,4
163 subi r4,r4,4
164 li r0,0
16550: stwu r0,4(r3)
166 cmpw cr0,r3,r4
167 bne 50b
16890: mr r9,r1 /* Save old stack pointer (in case it matters) */
169 lis r1,.stack@h
170 ori r1,r1,.stack@l
171 addi r1,r1,4096*2
172 subi r1,r1,256
173 li r2,0x000F /* Mask pointer to 16-byte boundary */
174 andc r1,r1,r2
175
176 /*
177 * Exec kernel loader
178 */
179 mr r3,r8 /* Load point */
180 mr r4,r7 /* Program length */
181 mr r5,r6 /* Checksum */
182 mr r6,r11 /* Residual data */
183 mr r7,r25 /* Validated OFW interface */
184 bl load_kernel
185
186 /*
187 * Make sure the kernel knows we don't have things set in
188 * registers. -- Tom
189 */
190 li r4,0
191 li r5,0
192 li r6,0
193
194 /*
195 * Start at the begining.
196 */
197#ifdef CONFIG_PPC_MULTIPLATFORM
198 li r9,0xc
199 mtlr r9
200 /* tell kernel we're prep, by putting 0xdeadc0de at KERNELLOAD,
201 * and tell the kernel to start on the 4th instruction since we
202 * overwrite the first 3 sometimes (which are 'nop').
203 */
204 lis r10,0xdeadc0de@h
205 ori r10,r10,0xdeadc0de@l
206 li r9,0
207 stw r10,0(r9)
208#else
209 li r9,0
210 mtlr r9
211#endif
212 blr
213
214 .comm .stack,4096*2,4