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