1 | /* |
---|
2 | * Mini-loader for the SVGM and MVME5500 BSP. |
---|
3 | * |
---|
4 | * $Id$ |
---|
5 | * |
---|
6 | * Copyright (C) 2003, 2004 |
---|
7 | * Author: Till Straumann, 10/2001 <strauman@slac.stanford.edu> |
---|
8 | * |
---|
9 | * Some ideas are borrowed from the powerpc/shared/bootloader |
---|
10 | * by |
---|
11 | * Copyright (C) 1998, 1999 Gabriel Paubert, paubert@iram.es |
---|
12 | * Copyright (C) 1999 Eric Valette. valette@crf.canon.fr |
---|
13 | * |
---|
14 | * |
---|
15 | * The SVGM firmware is unable to load the RTEMS image below |
---|
16 | * 0x2000 (I believe their stack is growing below 0x1000) ? |
---|
17 | * |
---|
18 | * The code provided by this file is responsible for the performing |
---|
19 | * the following steps: |
---|
20 | * |
---|
21 | * 1) Save commandline parameters to an area that is |
---|
22 | * a) not covered by the downloaded image |
---|
23 | * b) will not be overwritten by the moved image |
---|
24 | * nor the final BSS segment (rtems clears BSS |
---|
25 | * before saving the command line). |
---|
26 | * 2) Initialize and setup the memory controller to prepare the |
---|
27 | * SDRAM before moving the image to it. |
---|
28 | * 3) Move the entire image (including this very file) to |
---|
29 | * its final location starting at 0x0000. |
---|
30 | * It is important to note that _NO_STACK_ is available |
---|
31 | * during this step. Also, there is probably no return to |
---|
32 | * Monitor because relocating RTEMS will destroy vital Monitor |
---|
33 | * data (such as its stack). |
---|
34 | * 3) Flush the cache to make sure the relocated image is actually |
---|
35 | * in memory. |
---|
36 | * 4) setup RTEMS environment (initial register values), most |
---|
37 | * notably an initial STACK. The initial stack may be small and |
---|
38 | * is used by RTEMS only at a very early stage. |
---|
39 | * A safe place for the stack seems to be the 00..0x7f area. |
---|
40 | * NOTE: we should respect the MAILBOX area 0x80..0xff! |
---|
41 | * 5) switch the MMU off (because that's what RTEMS is expecting |
---|
42 | * it to be at startup). |
---|
43 | * 6) fire up rtems... |
---|
44 | * |
---|
45 | * |
---|
46 | * Calling convention: |
---|
47 | * R1: Monitor SP |
---|
48 | * R3: command line string start |
---|
49 | * R4: command line string end + 1 |
---|
50 | * R5: where Monitor put the image |
---|
51 | * if R5 is 0, the preloader will use its entry point |
---|
52 | * as the image starting address. |
---|
53 | * See NOTE below. |
---|
54 | * R6: end of the image (i.e. R6-R5 is the image length) |
---|
55 | * if R6 is 0, _edata will be used as the image length |
---|
56 | * See NOTE below. |
---|
57 | * |
---|
58 | * NOTE: if the symbol DONT_USE_R5_ENTRY is defined, |
---|
59 | * R5/R6 are never used and the necessary parameters are |
---|
60 | * determined at runtime (R5) / linkage (R6) [_edata] |
---|
61 | * |
---|
62 | * ASSUMPTIONS: |
---|
63 | * The code RELIES on the assumption that the image will be |
---|
64 | * moved DOWNWARDS in memory and that the this loader is |
---|
65 | * prepended to the image, i.e. it is safe to do |
---|
66 | * codemove(codemove,0,codemove_end - codemove); |
---|
67 | * (*0)(codemove_end, codemove_end-codemove, __rtems_end-codemove_end); |
---|
68 | * where codemove(from, to, nbytes) is defined as |
---|
69 | * codemove(from, to, nbytes) { while (nbytes--) *(to++)=*(from++); } |
---|
70 | * Implicit to these assumptions is the assumption that the destination |
---|
71 | * address is cache block aligned. |
---|
72 | * Furthermore, the byte count is assumed to be a multiple |
---|
73 | * of four |
---|
74 | * |
---|
75 | */ |
---|
76 | #if 0 |
---|
77 | /* TODO: I dont know where the appropriate CPU model is to be defined |
---|
78 | * when including this to get PPC_CACHE_ALIGNMENT I get an error... |
---|
79 | */ |
---|
80 | #include <rtems/score/ppc.h> |
---|
81 | #else |
---|
82 | #ifndef PPC_CACHE_ALIGNMENT |
---|
83 | #define PPC_CACHE_ALIGNMENT 32 |
---|
84 | #endif |
---|
85 | #endif |
---|
86 | |
---|
87 | #include <rtems/score/cpu.h> |
---|
88 | #include <rtems/asm.h> |
---|
89 | |
---|
90 | /* Note that major modifications may be needed |
---|
91 | * if DESTINATION_ADDR is not 0 |
---|
92 | */ |
---|
93 | #define KERNELBASE 0x0 |
---|
94 | #define INITIAL_STACK 0x78 /* 8-byte aligned */ |
---|
95 | #define CACHE_LINE_SIZE PPC_CACHE_ALIGNMENT /* autodetect doesn't work, see below */ |
---|
96 | #define ASSUME_RTEMS_INSTALLS_VECTORS /* assume we need not load vectors */ |
---|
97 | #define DONT_USE_R5_ENTRY /* always dynamically determine the address we're running from */ |
---|
98 | |
---|
99 | /* put this into its own section which we want to |
---|
100 | * be loaded at the very beginning. We should probably |
---|
101 | * not use more than 255 bytes. |
---|
102 | */ |
---|
103 | PUBLIC_VAR(__rtems_start) |
---|
104 | PUBLIC_VAR(__rtems_entry_point) |
---|
105 | PUBLIC_VAR(__rtems_end) |
---|
106 | .section .mvme5500_preloader_section,"awx",@progbits |
---|
107 | preload: |
---|
108 | /* find out where we are */ |
---|
109 | bl here |
---|
110 | here: |
---|
111 | /* MOTLoad had MSR_EE turned on. Disable it.*/ |
---|
112 | mfmsr r0 |
---|
113 | xori r0, r0, MSR_EE |
---|
114 | mtmsr r0 |
---|
115 | mflr r5 |
---|
116 | addi r5,r5,-(here-preload) |
---|
117 | lis r27,_edata@h |
---|
118 | ori r27,r27,_edata@l |
---|
119 | |
---|
120 | /* at this point the register contents are |
---|
121 | * R3: command line start |
---|
122 | * R4: R3 + command line length |
---|
123 | * R5: address we are running from / loaded to |
---|
124 | * R27: image end |
---|
125 | */ |
---|
126 | |
---|
127 | /* save command line start */ |
---|
128 | mr r6, r3 |
---|
129 | /* save the command line parameters if they are to be overwritten */ |
---|
130 | sub. r17, r4, r3 /* string length */ |
---|
131 | ble leaveparms /* <=0 -> no parameters */ |
---|
132 | /* copy has to be out of the way of the bss; therefore we must |
---|
133 | * put the string out of the way of both, the current end of |
---|
134 | * the image (without bss) AND the end of the loaded image |
---|
135 | * (including bss): |
---|
136 | * |......image.........| downloaded image |
---|
137 | * |image_bss...........| loaded image with bss appended |
---|
138 | * |
---|
139 | * ^ safe place for string |
---|
140 | * |
---|
141 | * the alternative scenario looks like this: |
---|
142 | * |..image.............| downloaded image |
---|
143 | * |image_bss...........| loaded image with bss appended |
---|
144 | * ^ safe place for string |
---|
145 | */ |
---|
146 | lis r18, __rtems_end+0x10000@h /* round up, save one instruction */ |
---|
147 | add r16, r5, r27 /* image end + 1 */ |
---|
148 | cmpw r16, r18 |
---|
149 | bge ishighenough |
---|
150 | mr r16,r18 /* __rtems_end is higher than |
---|
151 | * the image end |
---|
152 | * (without bss) |
---|
153 | */ |
---|
154 | ishighenough: |
---|
155 | cmpw r16, r3 /* destination start > current string start ? */ |
---|
156 | ble leaveparms /* string already after dst, leave it */ |
---|
157 | /* copy string from the last byte downwards */ |
---|
158 | add r6, r16, r17 /* last byte of destination + 1 */ |
---|
159 | mtctr r17 |
---|
160 | 1: |
---|
161 | lbzu r3, -1(r4) |
---|
162 | stbu r3, -1(r6) |
---|
163 | bdnz 1b |
---|
164 | leaveparms: |
---|
165 | add r7, r6, r17 /* destination + strlen */ |
---|
166 | |
---|
167 | #ifndef CACHE_LINE_SIZE |
---|
168 | /* Oh well, Monitor firmware has inhibited the cache, so this |
---|
169 | * nice routine doesn't work... |
---|
170 | */ |
---|
171 | /* figure out the cache line size */ |
---|
172 | li r16, 0x80 |
---|
173 | cmpw r5, r16 /* 'from' must be > 0x80 */ |
---|
174 | blt panic |
---|
175 | |
---|
176 | 1: /* store some arbitrary, nonzero stuff in 0..0x7c */ |
---|
177 | stwu r16,-4(r16) |
---|
178 | cmpwi r16,0 |
---|
179 | bne 1b |
---|
180 | dcbz 0,r16 /* zero out one cache line */ |
---|
181 | subi r16,r16,4 |
---|
182 | 2: lwzu r0,4(r16) /* search for a non-zero word */ |
---|
183 | cmpwi r0,0 |
---|
184 | beq 2b |
---|
185 | /* OK, r16 now hold the size of a cache line in bytes */ |
---|
186 | #else |
---|
187 | li r16,CACHE_LINE_SIZE |
---|
188 | #endif |
---|
189 | |
---|
190 | lis r3,preload@h |
---|
191 | ori r3,r3,preload@l |
---|
192 | mr r4,r5 /* from-addr */ |
---|
193 | li r5,_preload_size/* this is never > 16k */ |
---|
194 | /* now move ourselves to the link address ('preload'). |
---|
195 | * We set up the LR, so domove() 'returns' to the |
---|
196 | * relocated copy |
---|
197 | */ |
---|
198 | lis r0,return_here@h |
---|
199 | ori r0,r0,return_here@l |
---|
200 | mtlr r0 |
---|
201 | b domove /* move the preloader itself */ |
---|
202 | return_here: |
---|
203 | /* now we move the entire rest of the image */ |
---|
204 | #ifdef ASSUME_RTEMS_INSTALLS_VECTORS |
---|
205 | lis r3,__rtems_start@h |
---|
206 | ori r3,r3,__rtems_start@l |
---|
207 | lis r0,preload@h /* calculate/adjust from address */ |
---|
208 | ori r0,r0,preload@l |
---|
209 | sub r0,r3,r0 |
---|
210 | add r4,r4,r0 |
---|
211 | sub r5,r27,r3 |
---|
212 | #else |
---|
213 | add r3,r3,r5 /* add preloader size to destination */ |
---|
214 | add r4,r4,r5 /* and source addresses */ |
---|
215 | sub r5,r27,r5 /* length of the remaining rest */ |
---|
216 | #endif |
---|
217 | bl domove |
---|
218 | /* OK, now everything should be in place. |
---|
219 | * we are ready to start... |
---|
220 | */ |
---|
221 | /* R6: start of command line */ |
---|
222 | /* R7: end of command line +1 */ |
---|
223 | |
---|
224 | /* setup initial stack for rtems early boot */ |
---|
225 | lis r1, INITIAL_STACK |
---|
226 | /* disable the MMU and fire up rtems */ |
---|
227 | mfmsr r0 |
---|
228 | ori r0,r0,MSR_IR|MSR_DR|MSR_IP |
---|
229 | xori r0,r0,MSR_IR|MSR_DR |
---|
230 | mtsrr1 r0 |
---|
231 | lis r0,__rtems_entry_point@h |
---|
232 | ori r0,r0,__rtems_entry_point@l |
---|
233 | mtsrr0 r0 |
---|
234 | rfi |
---|
235 | |
---|
236 | /* domove(to, from, nbytes): |
---|
237 | * |
---|
238 | * move a R5 bytes from R4 to R3 and flush |
---|
239 | * the caches for the destination memory |
---|
240 | * region. R16 provides the cache line size. |
---|
241 | * DESTROYS: R0, R17, R18, CTR, CR |
---|
242 | */ |
---|
243 | domove: |
---|
244 | addi r0,r5,3 /* convert to word count */ |
---|
245 | srwi. r0,r0,2 |
---|
246 | beq 3f /* nothing to do */ |
---|
247 | cmpw r3,r4 /* from == to ? */ |
---|
248 | beq 3f |
---|
249 | mtctr r0 |
---|
250 | la r18,-4(r4) |
---|
251 | la r17,-4(r3) |
---|
252 | 1: lwzu r0,4(r18) |
---|
253 | stwu r0,4(r17) |
---|
254 | bdnz 1b /* move data */ |
---|
255 | /* now, we must flush the destination cache region */ |
---|
256 | #ifndef CACHE_LINE_SIZE |
---|
257 | cmpwi r16,0 |
---|
258 | beq 3f /* nothing to do */ |
---|
259 | #endif |
---|
260 | #if defined(CACHE_LINE_SIZE) && CACHE_LINE_SIZE > 0 |
---|
261 | add r17,r3,r5 /* target end pointer */ |
---|
262 | subi r0,r16,1 |
---|
263 | add r17,r17,r0 |
---|
264 | andc r17,r17,r0 /* cache aligned target end pointer */ |
---|
265 | mr r18,r3 |
---|
266 | 2: cmpw r18,r17 |
---|
267 | dcbst 0,r18 /* write out data cache line */ |
---|
268 | icbi 0,r18 /* invalidate corresponding i-cache line */ |
---|
269 | add r18,r18,r16 |
---|
270 | blt 2b |
---|
271 | sync /* make sure data is written back */ |
---|
272 | isync /* invalidate possibly preloaded instructions */ |
---|
273 | #endif |
---|
274 | 3: |
---|
275 | blr |
---|
276 | |
---|
277 | #if !defined(CACHE_LINE_SIZE) |
---|
278 | panic: |
---|
279 | li r10,0x63 |
---|
280 | mfmsr r0 |
---|
281 | ori r0,r0,MSR_IP |
---|
282 | mtmsr r0 |
---|
283 | sc |
---|
284 | #endif |
---|
285 | |
---|
286 | /* DONT PUT ANY CODE BELOW HERE */ |
---|
287 | _preload_size = . - preload |
---|