bootxx.c revision 1.13 1 /* $NetBSD: bootxx.c,v 1.13 2004/03/12 19:13:37 wrstuden Exp $ */
2
3 /*
4 * Copyright (C) 1995, 1996 Wolfgang Solfrank.
5 * Copyright (C) 1995, 1996 TooLs GmbH.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by TooLs GmbH.
19 * 4. The name of TooLs GmbH may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
28 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #include <sys/types.h>
35 #include <powerpc/oea/bat.h>
36
37 #include <sys/bootblock.h>
38
39 int (*openfirmware)(void *);
40
41 /*
42 * 32 KB of stack with 32 bytes overpad
43 * (see below)
44 */
45 int32_t __attribute__((aligned(16))) stack[8192 + 8];
46
47 struct shared_bbinfo bbinfo = {
48 { MACPPC_BBINFO_MAGIC },
49 0,
50 SHARED_BBINFO_MAXBLOCKS,
51 { 0 }
52 };
53
54 #ifndef DEFAULT_ENTRY_POINT
55 #define DEFAULT_ENTRY_POINT 0xE00000
56 #endif
57
58 void (*entry_point)(int, int, void *) = (void *)DEFAULT_ENTRY_POINT;
59
60
61 asm(
62 " .text \n"
63 " .align 2 \n"
64 " .globl _start \n"
65 "_start: \n"
66
67 " lis %r8,(_start)@ha \n"
68 " addi %r8,8,(_start)@l\n"
69 " li %r9,0x40 \n" /* loop 64 times (for 2048 bytes of bootxx) */
70 " mtctr %r9 \n"
71 "1: \n"
72 " dcbf %r0,%r8 \n"
73 " icbi %r0,%r8 \n"
74 " addi %r8,%r8,0x20 \n"
75 " bdnz 1b \n"
76 " sync \n"
77
78 " li %r0,0 \n"
79 " mtdbatu 3,%r0 \n"
80 " mtibatu 3,%r0 \n"
81 " isync \n"
82 " li %r8,0x1ffe \n" /* map the lowest 256MB */
83 " li %r9,0x22 \n" /* BAT_I */
84 " mtdbatl 3,%r9 \n"
85 " mtdbatu 3,%r8 \n"
86 " mtibatl 3,%r9 \n"
87 " mtibatu 3,%r8 \n"
88 " isync \n"
89
90 /*
91 * setup 32 KB of stack with 32 bytes overpad (see above)
92 */
93 " lis %r1,(stack+32768)@ha\n"
94 " addi %r1,%r1,(stack+32768)@l\n"
95 " stw %r0,0(%r1) \n" /* terminate the frame link chain */
96
97 " b startup \n"
98 );
99
100
101 static __inline int
102 OF_finddevice(name)
103 char *name;
104 {
105 static struct {
106 char *name;
107 int nargs;
108 int nreturns;
109 char *device;
110 int phandle;
111 } args = {
112 "finddevice",
113 1,
114 1,
115 };
116
117 args.device = name;
118 openfirmware(&args);
119
120 return args.phandle;
121 }
122
123 static __inline int
124 OF_getprop(handle, prop, buf, buflen)
125 int handle;
126 char *prop;
127 void *buf;
128 int buflen;
129 {
130 static struct {
131 char *name;
132 int nargs;
133 int nreturns;
134 int phandle;
135 char *prop;
136 void *buf;
137 int buflen;
138 int size;
139 } args = {
140 "getprop",
141 4,
142 1,
143 };
144
145 args.phandle = handle;
146 args.prop = prop;
147 args.buf = buf;
148 args.buflen = buflen;
149 openfirmware(&args);
150
151 return args.size;
152 }
153
154 static __inline int
155 OF_open(dname)
156 char *dname;
157 {
158 static struct {
159 char *name;
160 int nargs;
161 int nreturns;
162 char *dname;
163 int handle;
164 } args = {
165 "open",
166 1,
167 1,
168 };
169
170 args.dname = dname;
171 openfirmware(&args);
172
173 return args.handle;
174 }
175
176 static __inline int
177 OF_read(handle, addr, len)
178 int handle;
179 void *addr;
180 int len;
181 {
182 static struct {
183 char *name;
184 int nargs;
185 int nreturns;
186 int ihandle;
187 void *addr;
188 int len;
189 int actual;
190 } args = {
191 "read",
192 3,
193 1,
194 };
195
196 args.ihandle = handle;
197 args.addr = addr;
198 args.len = len;
199 openfirmware(&args);
200
201 return args.actual;
202 }
203
204 static __inline int
205 OF_seek(handle, pos)
206 int handle;
207 u_quad_t pos;
208 {
209 static struct {
210 char *name;
211 int nargs;
212 int nreturns;
213 int handle;
214 int poshi;
215 int poslo;
216 int status;
217 } args = {
218 "seek",
219 3,
220 1,
221 };
222
223 args.handle = handle;
224 args.poshi = (int)(pos >> 32);
225 args.poslo = (int)pos;
226 openfirmware(&args);
227
228 return args.status;
229 }
230
231 static __inline int
232 OF_write(handle, addr, len)
233 int handle;
234 const void *addr;
235 int len;
236 {
237 static struct {
238 char *name;
239 int nargs;
240 int nreturns;
241 int ihandle;
242 const void *addr;
243 int len;
244 int actual;
245 } args = {
246 "write",
247 3,
248 1,
249 };
250
251 args.ihandle = handle;
252 args.addr = addr;
253 args.len = len;
254 openfirmware(&args);
255
256 return args.actual;
257 }
258
259 int stdout;
260
261 void
262 putstrn(const char *s, size_t n)
263 {
264 OF_write(stdout, s, n);
265 }
266
267 #define putstr(x) putstrn((x),sizeof(x)-1)
268 #define putc(x) do { char __x = (x) ; putstrn(&__x, 1); } while (0)
269
270
271 void
272 startup(arg1, arg2, openfirm)
273 int arg1, arg2;
274 void *openfirm;
275 {
276 int fd, blk, chosen, options, j;
277 size_t i;
278 char *addr;
279 char bootpath[128];
280
281 openfirmware = openfirm;
282
283 chosen = OF_finddevice("/chosen");
284 if (OF_getprop(chosen, "bootpath", bootpath, sizeof(bootpath)) == 1) {
285 /*
286 * buggy firmware doesn't set bootpath...
287 */
288 options = OF_finddevice("/options");
289 OF_getprop(options, "boot-device", bootpath, sizeof(bootpath));
290 }
291 if (OF_getprop(chosen, "stdout", &stdout, sizeof(stdout))
292 != sizeof(stdout))
293 stdout = -1;
294
295 /*
296 * "scsi/sd@0:0" --> "scsi/sd@0"
297 */
298 for (i = 0; i < sizeof(bootpath); i++) {
299 if (bootpath[i] == ':')
300 bootpath[i] = 0;
301 if (bootpath[i] == 0)
302 break;
303 }
304
305 putstr("\r\nOF_open bootpath=");
306 putstrn(bootpath, i);
307 fd = OF_open(bootpath);
308
309 addr = (char *)entry_point;
310 putstr("\r\nread stage 2 blocks: ");
311 for (j = 0; j < bbinfo.bbi_block_count; j++) {
312 if ((blk = bbinfo.bbi_block_table[j]) == 0)
313 break;
314 putc('0' + j % 10);
315 OF_seek(fd, (u_quad_t)blk * 512);
316 OF_read(fd, addr, bbinfo.bbi_block_size);
317 addr += bbinfo.bbi_block_size;
318 }
319 putstr(". done!\r\nstarting stage 2...\r\n");
320
321 /*
322 * enable D/I cache
323 */
324 asm(
325 "mtdbatu 3,%0\n\t"
326 "mtdbatl 3,%1\n\t"
327 "mtibatu 3,%0\n\t"
328 "mtibatl 3,%1\n\t"
329 "isync"
330 :: "r"(BATU(0, BAT_BL_256M, BAT_Vs)),
331 "r"(BATL(0, 0, BAT_PP_RW)));
332
333 entry_point(0, 0, openfirm);
334 for (;;); /* just in case */
335 }
336