bootxx.c revision 1.11 1 1.11 matt /* $NetBSD: bootxx.c,v 1.11 2003/02/28 05:24:56 matt 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.10 matt asm(
62 1.10 matt " .text \n"
63 1.10 matt " .align 2 \n"
64 1.10 matt " .globl _start \n"
65 1.10 matt "_start: \n"
66 1.10 matt
67 1.10 matt " lis %r8,(_start)@ha \n"
68 1.10 matt " addi %r8,8,(_start)@l\n"
69 1.10 matt " li %r9,0x40 \n" /* loop 64 times (for 2048 bytes of bootxx) */
70 1.10 matt " mtctr %r9 \n"
71 1.10 matt "1: \n"
72 1.10 matt " dcbf %r0,%r8 \n"
73 1.10 matt " icbi %r0,%r8 \n"
74 1.10 matt " addi %r8,%r8,0x20 \n"
75 1.10 matt " bdnz 1b \n"
76 1.10 matt " sync \n"
77 1.10 matt
78 1.10 matt " li %r0,0 \n"
79 1.10 matt " mtdbatu 3,%r0 \n"
80 1.10 matt " mtibatu 3,%r0 \n"
81 1.10 matt " isync \n"
82 1.10 matt " li %r8,0x1ffe \n" /* map the lowest 256MB */
83 1.10 matt " li %r9,0x22 \n" /* BAT_I */
84 1.10 matt " mtdbatl 3,%r9 \n"
85 1.10 matt " mtdbatu 3,%r8 \n"
86 1.10 matt " mtibatl 3,%r9 \n"
87 1.10 matt " mtibatu 3,%r8 \n"
88 1.10 matt " isync \n"
89 1.10 matt
90 1.10 matt /*
91 1.10 matt * setup 32 KB of stack with 32 bytes overpad (see above)
92 1.10 matt */
93 1.10 matt " lis %r1,(stack+32768)@ha\n"
94 1.10 matt " addi %r1,%r1,(stack+32768)@l\n"
95 1.10 matt " stw %r0,0(%r1) \n" /* terminate the frame link chain */
96 1.1 tsubai
97 1.10 matt " b startup \n"
98 1.10 matt );
99 1.1 tsubai
100 1.1 tsubai
101 1.1 tsubai static __inline int
102 1.1 tsubai OF_finddevice(name)
103 1.1 tsubai char *name;
104 1.1 tsubai {
105 1.1 tsubai static struct {
106 1.1 tsubai char *name;
107 1.1 tsubai int nargs;
108 1.1 tsubai int nreturns;
109 1.1 tsubai char *device;
110 1.1 tsubai int phandle;
111 1.1 tsubai } args = {
112 1.1 tsubai "finddevice",
113 1.1 tsubai 1,
114 1.1 tsubai 1,
115 1.1 tsubai };
116 1.1 tsubai
117 1.1 tsubai args.device = name;
118 1.1 tsubai openfirmware(&args);
119 1.1 tsubai
120 1.1 tsubai return args.phandle;
121 1.1 tsubai }
122 1.1 tsubai
123 1.1 tsubai static __inline int
124 1.1 tsubai OF_getprop(handle, prop, buf, buflen)
125 1.1 tsubai int handle;
126 1.1 tsubai char *prop;
127 1.1 tsubai void *buf;
128 1.1 tsubai int buflen;
129 1.1 tsubai {
130 1.1 tsubai static struct {
131 1.1 tsubai char *name;
132 1.1 tsubai int nargs;
133 1.1 tsubai int nreturns;
134 1.1 tsubai int phandle;
135 1.1 tsubai char *prop;
136 1.1 tsubai void *buf;
137 1.1 tsubai int buflen;
138 1.1 tsubai int size;
139 1.1 tsubai } args = {
140 1.1 tsubai "getprop",
141 1.1 tsubai 4,
142 1.1 tsubai 1,
143 1.1 tsubai };
144 1.1 tsubai
145 1.1 tsubai args.phandle = handle;
146 1.1 tsubai args.prop = prop;
147 1.1 tsubai args.buf = buf;
148 1.1 tsubai args.buflen = buflen;
149 1.1 tsubai openfirmware(&args);
150 1.1 tsubai
151 1.1 tsubai return args.size;
152 1.1 tsubai }
153 1.1 tsubai
154 1.1 tsubai static __inline int
155 1.1 tsubai OF_open(dname)
156 1.1 tsubai char *dname;
157 1.1 tsubai {
158 1.1 tsubai static struct {
159 1.1 tsubai char *name;
160 1.1 tsubai int nargs;
161 1.1 tsubai int nreturns;
162 1.1 tsubai char *dname;
163 1.1 tsubai int handle;
164 1.1 tsubai } args = {
165 1.1 tsubai "open",
166 1.1 tsubai 1,
167 1.1 tsubai 1,
168 1.1 tsubai };
169 1.1 tsubai
170 1.1 tsubai args.dname = dname;
171 1.1 tsubai openfirmware(&args);
172 1.1 tsubai
173 1.1 tsubai return args.handle;
174 1.1 tsubai }
175 1.1 tsubai
176 1.1 tsubai static __inline int
177 1.1 tsubai OF_read(handle, addr, len)
178 1.1 tsubai int handle;
179 1.1 tsubai void *addr;
180 1.1 tsubai int len;
181 1.1 tsubai {
182 1.1 tsubai static struct {
183 1.1 tsubai char *name;
184 1.1 tsubai int nargs;
185 1.1 tsubai int nreturns;
186 1.1 tsubai int ihandle;
187 1.1 tsubai void *addr;
188 1.1 tsubai int len;
189 1.1 tsubai int actual;
190 1.1 tsubai } args = {
191 1.1 tsubai "read",
192 1.1 tsubai 3,
193 1.1 tsubai 1,
194 1.1 tsubai };
195 1.1 tsubai
196 1.1 tsubai args.ihandle = handle;
197 1.1 tsubai args.addr = addr;
198 1.1 tsubai args.len = len;
199 1.1 tsubai openfirmware(&args);
200 1.1 tsubai
201 1.1 tsubai return args.actual;
202 1.1 tsubai }
203 1.1 tsubai
204 1.1 tsubai static __inline int
205 1.1 tsubai OF_seek(handle, pos)
206 1.1 tsubai int handle;
207 1.1 tsubai u_quad_t pos;
208 1.1 tsubai {
209 1.1 tsubai static struct {
210 1.1 tsubai char *name;
211 1.1 tsubai int nargs;
212 1.1 tsubai int nreturns;
213 1.1 tsubai int handle;
214 1.1 tsubai int poshi;
215 1.1 tsubai int poslo;
216 1.1 tsubai int status;
217 1.1 tsubai } args = {
218 1.1 tsubai "seek",
219 1.1 tsubai 3,
220 1.1 tsubai 1,
221 1.1 tsubai };
222 1.1 tsubai
223 1.1 tsubai args.handle = handle;
224 1.1 tsubai args.poshi = (int)(pos >> 32);
225 1.1 tsubai args.poslo = (int)pos;
226 1.1 tsubai openfirmware(&args);
227 1.1 tsubai
228 1.1 tsubai return args.status;
229 1.1 tsubai }
230 1.1 tsubai
231 1.8 lukem static __inline int
232 1.8 lukem OF_write(handle, addr, len)
233 1.8 lukem int handle;
234 1.11 matt const void *addr;
235 1.8 lukem int len;
236 1.8 lukem {
237 1.8 lukem static struct {
238 1.8 lukem char *name;
239 1.8 lukem int nargs;
240 1.8 lukem int nreturns;
241 1.8 lukem int ihandle;
242 1.11 matt const void *addr;
243 1.8 lukem int len;
244 1.8 lukem int actual;
245 1.8 lukem } args = {
246 1.8 lukem "write",
247 1.8 lukem 3,
248 1.8 lukem 1,
249 1.8 lukem };
250 1.8 lukem
251 1.8 lukem args.ihandle = handle;
252 1.8 lukem args.addr = addr;
253 1.8 lukem args.len = len;
254 1.8 lukem openfirmware(&args);
255 1.8 lukem
256 1.8 lukem return args.actual;
257 1.8 lukem }
258 1.8 lukem
259 1.8 lukem int stdout;
260 1.8 lukem
261 1.8 lukem void
262 1.8 lukem putstrn(const char *s, size_t n)
263 1.8 lukem {
264 1.8 lukem OF_write(stdout, s, n);
265 1.8 lukem }
266 1.8 lukem
267 1.8 lukem #define putstr(x) putstrn((x),sizeof(x)-1)
268 1.8 lukem #define putc(x) do { char __x = (x) ; putstrn(&__x, 1); } while (0)
269 1.8 lukem
270 1.8 lukem
271 1.1 tsubai void
272 1.1 tsubai startup(arg1, arg2, openfirm)
273 1.1 tsubai int arg1, arg2;
274 1.1 tsubai void *openfirm;
275 1.1 tsubai {
276 1.11 matt int fd, blk, chosen, options, j;
277 1.11 matt size_t 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.11 matt for (j = 0; j < bbinfo.bbi_block_count; j++) {
312 1.11 matt if ((blk = bbinfo.bbi_block_table[j]) == 0)
313 1.6 lukem break;
314 1.11 matt putc('0' + j % 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.11 matt asm(
325 1.11 matt "mtdbatu 3,%0\n\t"
326 1.11 matt "mtdbatl 3,%1\n\t"
327 1.11 matt "mtibatu 3,%0\n\t"
328 1.11 matt "mtibatl 3,%1\n\t"
329 1.11 matt "isync"
330 1.11 matt :: "r"(BATU(0, BAT_BL_256M, BAT_Vs)),
331 1.11 matt "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