bootxx.c revision 1.17 1 /* $NetBSD: bootxx.c,v 1.17 2009/03/14 15:36:09 dsl 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(char *name)
103 {
104 static struct {
105 char *name;
106 int nargs;
107 int nreturns;
108 char *device;
109 int phandle;
110 } args = {
111 "finddevice",
112 1,
113 1,
114 };
115
116 args.device = name;
117 openfirmware(&args);
118
119 return args.phandle;
120 }
121
122 static inline int
123 OF_getprop(int handle, char *prop, void *buf, int buflen)
124 {
125 static struct {
126 char *name;
127 int nargs;
128 int nreturns;
129 int phandle;
130 char *prop;
131 void *buf;
132 int buflen;
133 int size;
134 } args = {
135 "getprop",
136 4,
137 1,
138 };
139
140 args.phandle = handle;
141 args.prop = prop;
142 args.buf = buf;
143 args.buflen = buflen;
144 openfirmware(&args);
145
146 return args.size;
147 }
148
149 static inline int
150 OF_open(char *dname)
151 {
152 static struct {
153 char *name;
154 int nargs;
155 int nreturns;
156 char *dname;
157 int handle;
158 } args = {
159 "open",
160 1,
161 1,
162 };
163
164 args.dname = dname;
165 openfirmware(&args);
166
167 return args.handle;
168 }
169
170 static inline int
171 OF_read(int handle, void *addr, int len)
172 {
173 static struct {
174 char *name;
175 int nargs;
176 int nreturns;
177 int ihandle;
178 void *addr;
179 int len;
180 int actual;
181 } args = {
182 "read",
183 3,
184 1,
185 };
186
187 args.ihandle = handle;
188 args.addr = addr;
189 args.len = len;
190 openfirmware(&args);
191
192 return args.actual;
193 }
194
195 static inline int
196 OF_seek(int handle, u_quad_t pos)
197 {
198 static struct {
199 char *name;
200 int nargs;
201 int nreturns;
202 int handle;
203 int poshi;
204 int poslo;
205 int status;
206 } args = {
207 "seek",
208 3,
209 1,
210 };
211
212 args.handle = handle;
213 args.poshi = (int)(pos >> 32);
214 args.poslo = (int)pos;
215 openfirmware(&args);
216
217 return args.status;
218 }
219
220 static inline int
221 OF_write(int handle, const void *addr, int len)
222 {
223 static struct {
224 char *name;
225 int nargs;
226 int nreturns;
227 int ihandle;
228 const void *addr;
229 int len;
230 int actual;
231 } args = {
232 "write",
233 3,
234 1,
235 };
236
237 args.ihandle = handle;
238 args.addr = addr;
239 args.len = len;
240 openfirmware(&args);
241
242 return args.actual;
243 }
244
245 int stdout;
246
247 void
248 putstrn(const char *s, size_t n)
249 {
250 OF_write(stdout, s, n);
251 }
252
253 #define putstr(x) putstrn((x),sizeof(x)-1)
254 #define putc(x) do { char __x = (x) ; putstrn(&__x, 1); } while (0)
255
256
257 void
258 startup(arg1, arg2, openfirm)
259 int arg1, arg2;
260 void *openfirm;
261 {
262 int fd, blk, chosen, options, j;
263 size_t i;
264 char *addr;
265 char bootpath[128];
266
267 openfirmware = openfirm;
268
269 chosen = OF_finddevice("/chosen");
270 if (OF_getprop(chosen, "bootpath", bootpath, sizeof(bootpath)) == 1) {
271 /*
272 * buggy firmware doesn't set bootpath...
273 */
274 options = OF_finddevice("/options");
275 OF_getprop(options, "boot-device", bootpath, sizeof(bootpath));
276 }
277 if (OF_getprop(chosen, "stdout", &stdout, sizeof(stdout))
278 != sizeof(stdout))
279 stdout = -1;
280
281 /*
282 * "scsi/sd@0:0" --> "scsi/sd@0"
283 */
284 for (i = 0; i < sizeof(bootpath); i++) {
285 if (bootpath[i] == ':')
286 bootpath[i] = 0;
287 if (bootpath[i] == 0)
288 break;
289 }
290
291 putstr("\r\nOF_open bootpath=");
292 putstrn(bootpath, i);
293 fd = OF_open(bootpath);
294
295 addr = (char *)entry_point;
296 putstr("\r\nread stage 2 blocks: ");
297 for (j = 0; j < bbinfo.bbi_block_count; j++) {
298 if ((blk = bbinfo.bbi_block_table[j]) == 0)
299 break;
300 putc('0' + j % 10);
301 OF_seek(fd, (u_quad_t)blk * 512);
302 OF_read(fd, addr, bbinfo.bbi_block_size);
303 addr += bbinfo.bbi_block_size;
304 }
305 putstr(". done!\r\nstarting stage 2...\r\n");
306
307 /*
308 * enable D/I cache
309 */
310 __asm(
311 "mtdbatu 3,%0\n\t"
312 "mtdbatl 3,%1\n\t"
313 "mtibatu 3,%0\n\t"
314 "mtibatl 3,%1\n\t"
315 "isync"
316 :: "r"(BATU(0, BAT_BL_256M, BAT_Vs)),
317 "r"(BATL(0, 0, BAT_PP_RW)));
318
319 entry_point(0, 0, openfirm);
320 for (;;); /* just in case */
321 }
322