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
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
|
/*
* Mini-loader for the SVGM BSP.
*
* Author: Till Straumann, 10/2001 <strauman@slac.stanford.edu>
*
* Some ideas are borrowed from the powerpc/shared/bootloader
* by
* Copyright (C) 1998, 1999 Gabriel Paubert, paubert@iram.es
* Copyright (C) 1999 Eric Valette. valette@crf.canon.fr
*
* The SMON firmware is unable to load the RTEMS image below
* 0x2000 (I believe their stack is growing below 0x1000).
*
* The code provided by this file is responsible for the performing
* the following steps:
*
* 1) Save commandline parameters to an area that is
* a) not covered by the downloaded image
* b) will not be overwritten by the moved image
* nor the final BSS segment (rtems clears BSS
* before saving the command line).
* 2) Move the entire image (including this very file) to
* its final location starting at 0x0000.
* It is important to note that _NO_STACK_ is available
* during this step. Also, there is probably no return to
* SMON because relocating RTEMS will destroy vital SMON
* data (such as its stack).
* 3) Flush the cache to make sure the relocated image is actually
* in memory.
* 4) setup RTEMS environment (initial register values), most
* notably an initial STACK. The initial stack may be small and
* is used by RTEMS only at a very early stage.
* A safe place for the stack seems to be the 00..0x7f area.
* NOTE: we should respect the MAILBOX area 0x80..0xff!
* 5) switch the MMU off (because that's what RTEMS is expecting
* it to be at startup).
* 6) fire up rtems...
*
*
* Calling convention:
* R1: SMON SP
* R3: command line string start
* R4: command line string end + 1
* R5: where SMON put the image
* if R5 is 0, the preloader will use its entry point
* as the image starting address.
* See NOTE below.
* R6: end of the image (i.e. R6-R5 is the image length)
* if R6 is 0, _edata will be used as the image length
* See NOTE below.
*
* NOTE: if the symbol DONT_USE_R5_ENTRY is defined,
* R5/R6 are never used and the necessary parameters are
* determined at runtime (R5) / linkage (R6) [_edata]
*
* ASSUMPTIONS:
* The code RELIES on the assumption that the image will be
* moved DOWNWARDS in memory and that the this loader is
* prepended to the image, i.e. it is safe to do
* codemove(codemove,0,codemove_end - codemove);
* (*0)(codemove_end, codemove_end-codemove, __rtems_end-codemove_end);
* where codemove(from, to, nbytes) is defined as
* codemove(from, to, nbytes) { while (nbytes--) *(to++)=*(from++); }
* Implicit to these assumptions is the assumption that the destination
* address is cache block aligned.
* Furthermore, the byte count is assumed to be a multiple
* of four
*
*/
#if 0
#include <rtems/score/powerpc.h>
#else
#ifndef PPC_CACHE_ALIGNMENT
#define PPC_CACHE_ALIGNMENT 32
#endif
#endif
#include <rtems/score/cpu.h>
#include <rtems/asm.h>
/* Note that major modifications may be needed
* if DESTINATION_ADDR is not 0
*/
#define KERNELBASE 0x0
#define INITIAL_STACK 0x70 /* 16-byte aligned */
#define CACHE_LINE_SIZE PPC_CACHE_ALIGNMENT /* autodetect doesn't work, see below */
#define ASSUME_RTEMS_INSTALLS_VECTORS /* assume we need not load vectors */
#define DONT_USE_R5_ENTRY /* always dynamically determine the address we're running from */
/* put this into its own section which we want to
* be loaded at the very beginning. We should probably
* not use more than 255 bytes.
*/
PUBLIC_VAR(__rtems_start)
PUBLIC_VAR(__rtems_entry_point)
PUBLIC_VAR(__rtems_end)
.section .entry_point_section,"awx",@progbits
preload:
/* find out where we are */
bl here
here:
xor r0,r0,r0
mtmsr r0 /* clear MSR to known state */
mflr r5
addi r5,r5,-(here-preload)
lis r27,_edata@h
ori r27,r27,_edata@l
/* at this point the register contents are
* R3: command line start
* R4: R3 + command line length
* R5: address we are running from / loaded to
* R27: image end
*/
/* save command line start */
mr r6, r3
/* save the command line parameters if they are to be overwritten */
sub. r17, r4, r3 /* string length */
ble leaveparms /* <=0 -> no parameters */
/* copy has to be out of the way of the bss; therefore we must
* put the string out of the way of both, the current end of
* the image (without bss) AND the end of the loaded image
* (including bss):
* |......image.........| downloaded image
* |image_bss...........| loaded image with bss appended
*
* ^ safe place for string
*
* the alternative scenario looks like this:
* |..image.............| downloaded image
* |image_bss...........| loaded image with bss appended
* ^ safe place for string
*/
lis r18, __rtems_end+0x10000@h /* round up, save one instruction */
add r16, r5, r27 /* image end + 1 */
cmpw r16, r18
bge ishighenough
mr r16,r18 /* __rtems_end is higher than the image end
* (without bss)
*/
ishighenough:
cmpw r16, r3 /* destination start > current string start ? */
ble leaveparms /* string already after dst, leave it */
/* copy string from the last byte downwards */
add r6, r16, r17 /* last byte of destination + 1 */
mtctr r17
1:
lbzu r3, -1(r4)
stbu r3, -1(r6)
bdnz 1b
leaveparms:
add r7, r6, r17 /* destination + strlen */
#ifndef CACHE_LINE_SIZE
/* Oh well, SMON has inhibited the cache, so this
* nice routine doesn't work...
*/
/* figure out the cache line size */
li r16, 0x80
cmpw r5, r16 /* 'from' must be > 0x80 */
blt panic
1: /* store some arbitrary, nonzero stuff in 0..0x7c */
stwu r16,-4(r16)
cmpwi r16,0
bne 1b
dcbz 0,r16 /* zero out one cache line */
subi r16,r16,4
2: lwzu r0,4(r16) /* search for a non-zero word */
cmpwi r0,0
beq 2b
/* OK, r16 now hold the size of a cache line in bytes */
#else
li r16,CACHE_LINE_SIZE
#endif
lis r3,preload@h
ori r3,r3,preload@l
mr r4,r5 /* from-addr */
li r5,_preload_size/* this is never > 16k */
/* now move ourselves to the link address ('preload').
* We set up the LR, so domove() 'returns' to the
* relocated copy
*/
lis r0,return_here@h
ori r0,r0,return_here@l
mtlr r0
b domove /* move the preloader itself */
return_here:
/* now we move the entire rest of the image */
#ifdef ASSUME_RTEMS_INSTALLS_VECTORS
lis r3,__rtems_start@h
ori r3,r3,__rtems_start@l
lis r0,preload@h /* calculate/adjust from address */
ori r0,r0,preload@l
sub r0,r3,r0
add r4,r4,r0
sub r5,r27,r3
#else
add r3,r3,r5 /* add preloader size to destination */
add r4,r4,r5 /* and source addresses */
sub r5,r27,r5 /* length of the remaining rest */
#endif
bl domove
/* OK, now everything should be in place.
* we are ready to start...
*/
/* setup initial stack for rtems early boot */
li r1,INITIAL_STACK
/* tag TOS with a NULL pointer (for stack trace) */
li r0, 0
stw r0, 0(r1)
/* disable the MMU and fire up rtems */
mfmsr r0
ori r0,r0,MSR_IR|MSR_DR|MSR_IP|MSR_ME
xori r0,r0,MSR_IR|MSR_DR
mtsrr1 r0
lis r0,__rtems_entry_point@h
ori r0,r0,__rtems_entry_point@l
mtsrr0 r0
/* R6: start of command line */
/* R7: end of command line +1 */
rfi
/* domove(to, from, nbytes):
*
* move a R5 bytes from R4 to R3 and flush
* the caches for the destination memory
* region. R16 provides the cache line size.
* DESTROYS: R0, R17, R18, CTR, CR
*/
domove:
addi r0,r5,3 /* convert to word count */
srwi. r0,r0,2
beq 3f /* nothing to do */
cmpw r3,r4 /* from == to ? */
beq 3f
mtctr r0
la r18,-4(r4)
la r17,-4(r3)
1: lwzu r0,4(r18)
stwu r0,4(r17)
bdnz 1b /* move data */
/* now, we must flush the destination cache region */
#ifndef CACHE_LINE_SIZE
cmpwi r16,0
beq 3f /* nothing to do */
#endif
#if defined(CACHE_LINE_SIZE) && CACHE_LINE_SIZE > 0
add r17,r3,r5 /* target end pointer */
subi r0,r16,1
add r17,r17,r0
andc r17,r17,r0 /* cache aligned target end pointer */
mr r18,r3
2: cmpw r18,r17
dcbst 0,r18 /* write out data cache line */
icbi 0,r18 /* invalidate corresponding i-cache line */
add r18,r18,r16
blt 2b
sync /* make sure data is written back */
isync /* invalidate possibly preloaded instructions */
#endif
3:
blr
#if !defined(CACHE_LINE_SIZE)
panic:
li r10,0x63
mfmsr r0
ori r0,r0,MSR_IP
mtmsr r0
sc
#endif
/* DONT PUT ANY CODE BELOW HERE */
_preload_size = . - preload
|