bootxx.c revision 1.19 1 1.19 scole /* $NetBSD: bootxx.c,v 1.19 2018/11/12 20:00:46 scole 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.12 matt #include <powerpc/oea/bat.h>
36 1.19 scole #include <powerpc/oea/spr.h>
37 1.1 tsubai
38 1.6 lukem #include <sys/bootblock.h>
39 1.6 lukem
40 1.1 tsubai int (*openfirmware)(void *);
41 1.8 lukem
42 1.8 lukem /*
43 1.8 lukem * 32 KB of stack with 32 bytes overpad
44 1.8 lukem * (see below)
45 1.8 lukem */
46 1.8 lukem int32_t __attribute__((aligned(16))) stack[8192 + 8];
47 1.1 tsubai
48 1.6 lukem struct shared_bbinfo bbinfo = {
49 1.6 lukem { MACPPC_BBINFO_MAGIC },
50 1.6 lukem 0,
51 1.6 lukem SHARED_BBINFO_MAXBLOCKS,
52 1.6 lukem { 0 }
53 1.6 lukem };
54 1.6 lukem
55 1.6 lukem #ifndef DEFAULT_ENTRY_POINT
56 1.13 wrstuden #define DEFAULT_ENTRY_POINT 0xE00000
57 1.6 lukem #endif
58 1.1 tsubai
59 1.6 lukem void (*entry_point)(int, int, void *) = (void *)DEFAULT_ENTRY_POINT;
60 1.1 tsubai
61 1.8 lukem
62 1.16 perry __asm(
63 1.10 matt " .text \n"
64 1.10 matt " .align 2 \n"
65 1.10 matt " .globl _start \n"
66 1.10 matt "_start: \n"
67 1.10 matt
68 1.10 matt " lis %r8,(_start)@ha \n"
69 1.10 matt " addi %r8,8,(_start)@l\n"
70 1.10 matt " li %r9,0x40 \n" /* loop 64 times (for 2048 bytes of bootxx) */
71 1.10 matt " mtctr %r9 \n"
72 1.19 scole " \n"
73 1.19 scole "1: dcbf %r0,%r8 \n"
74 1.10 matt " icbi %r0,%r8 \n"
75 1.10 matt " addi %r8,%r8,0x20 \n"
76 1.10 matt " bdnz 1b \n"
77 1.10 matt " sync \n"
78 1.10 matt
79 1.10 matt " li %r0,0 \n"
80 1.19 scole " \n" /* test for 601 cpu */
81 1.19 scole " mfspr %r9,287 \n" /* mfpvbr %r9 PVR = 287 */
82 1.19 scole " srwi %r9,%r9,0x10 \n"
83 1.19 scole " cmplwi %r9,0x02 \n" /* 601 cpu == 0x0001 */
84 1.19 scole " blt 2f \n" /* skip over non-601 BAT setup */
85 1.19 scole " \n"
86 1.19 scole " mtdbatu 3,%r0 \n" /* non-601 BAT */
87 1.10 matt " mtibatu 3,%r0 \n"
88 1.10 matt " isync \n"
89 1.10 matt " li %r8,0x1ffe \n" /* map the lowest 256MB */
90 1.10 matt " li %r9,0x22 \n" /* BAT_I */
91 1.10 matt " mtdbatl 3,%r9 \n"
92 1.10 matt " mtdbatu 3,%r8 \n"
93 1.10 matt " mtibatl 3,%r9 \n"
94 1.10 matt " mtibatu 3,%r8 \n"
95 1.10 matt " isync \n"
96 1.19 scole " b 3f \n"
97 1.19 scole " \n"
98 1.19 scole "2: mfmsr %r8 \n" /* 601 BAT */
99 1.19 scole " mtmsr %r0 \n"
100 1.19 scole " isync \n"
101 1.19 scole " \n"
102 1.19 scole " mtibatu 0,%r0 \n"
103 1.19 scole " mtibatu 1,%r0 \n"
104 1.19 scole " mtibatu 2,%r0 \n"
105 1.19 scole " mtibatu 3,%r0 \n"
106 1.19 scole " \n"
107 1.19 scole " li %r9,0x7f \n"
108 1.19 scole " mtibatl 0,%r9 \n"
109 1.19 scole " li %r9,0x1a \n"
110 1.19 scole " mtibatu 0,%r9 \n"
111 1.19 scole " \n"
112 1.19 scole " lis %r9,0x80 \n"
113 1.19 scole " addi %r9,%r9,0x7f \n"
114 1.19 scole " mtibatl 1,%r9 \n"
115 1.19 scole " lis %r9,0x80 \n"
116 1.19 scole " addi %r9,%r9,0x1a \n"
117 1.19 scole " mtibatu 1,%r9 \n"
118 1.19 scole " \n"
119 1.19 scole " lis %r9,0x100 \n"
120 1.19 scole " addi %r9,%r9,0x7f \n"
121 1.19 scole " mtibatl 2,%r9 \n"
122 1.19 scole " lis %r9,0x100 \n"
123 1.19 scole " addi %r9,%r9,0x1a \n"
124 1.19 scole " mtibatu 2,%r9 \n"
125 1.19 scole " \n"
126 1.19 scole " lis %r9,0x180 \n"
127 1.19 scole " addi %r9,%r9,0x7f \n"
128 1.19 scole " mtibatl 3,%r9 \n"
129 1.19 scole " lis %r9,0x180 \n"
130 1.19 scole " addi %r9,%r9,0x1a \n"
131 1.19 scole " mtibatu 3,%r9 \n"
132 1.19 scole " \n"
133 1.19 scole " isync \n"
134 1.19 scole " \n"
135 1.19 scole " mtmsr %r8 \n"
136 1.19 scole " isync \n"
137 1.19 scole " \n"
138 1.10 matt /*
139 1.10 matt * setup 32 KB of stack with 32 bytes overpad (see above)
140 1.10 matt */
141 1.19 scole "3: lis %r1,(stack+32768)@ha\n"
142 1.10 matt " addi %r1,%r1,(stack+32768)@l\n"
143 1.19 scole /*
144 1.19 scole * terminate the frame link chain,
145 1.19 scole * clear by bytes to avoid ppc601 alignment exceptions
146 1.19 scole */
147 1.19 scole " stb %r0,0(%r1) \n"
148 1.19 scole " stb %r0,1(%r1) \n"
149 1.19 scole " stb %r0,2(%r1) \n"
150 1.19 scole " stb %r0,3(%r1) \n"
151 1.1 tsubai
152 1.10 matt " b startup \n"
153 1.10 matt );
154 1.1 tsubai
155 1.1 tsubai
156 1.15 perry static inline int
157 1.17 dsl OF_finddevice(char *name)
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 *device;
164 1.1 tsubai int phandle;
165 1.1 tsubai } args = {
166 1.1 tsubai "finddevice",
167 1.1 tsubai 1,
168 1.1 tsubai 1,
169 1.1 tsubai };
170 1.1 tsubai
171 1.1 tsubai args.device = name;
172 1.1 tsubai openfirmware(&args);
173 1.1 tsubai
174 1.1 tsubai return args.phandle;
175 1.1 tsubai }
176 1.1 tsubai
177 1.15 perry static inline int
178 1.17 dsl OF_getprop(int handle, char *prop, void *buf, int buflen)
179 1.1 tsubai {
180 1.1 tsubai static struct {
181 1.1 tsubai char *name;
182 1.1 tsubai int nargs;
183 1.1 tsubai int nreturns;
184 1.1 tsubai int phandle;
185 1.1 tsubai char *prop;
186 1.1 tsubai void *buf;
187 1.1 tsubai int buflen;
188 1.1 tsubai int size;
189 1.1 tsubai } args = {
190 1.1 tsubai "getprop",
191 1.1 tsubai 4,
192 1.1 tsubai 1,
193 1.1 tsubai };
194 1.1 tsubai
195 1.1 tsubai args.phandle = handle;
196 1.1 tsubai args.prop = prop;
197 1.1 tsubai args.buf = buf;
198 1.1 tsubai args.buflen = buflen;
199 1.1 tsubai openfirmware(&args);
200 1.1 tsubai
201 1.1 tsubai return args.size;
202 1.1 tsubai }
203 1.1 tsubai
204 1.15 perry static inline int
205 1.17 dsl OF_open(char *dname)
206 1.1 tsubai {
207 1.1 tsubai static struct {
208 1.1 tsubai char *name;
209 1.1 tsubai int nargs;
210 1.1 tsubai int nreturns;
211 1.1 tsubai char *dname;
212 1.1 tsubai int handle;
213 1.1 tsubai } args = {
214 1.1 tsubai "open",
215 1.1 tsubai 1,
216 1.1 tsubai 1,
217 1.1 tsubai };
218 1.1 tsubai
219 1.1 tsubai args.dname = dname;
220 1.1 tsubai openfirmware(&args);
221 1.1 tsubai
222 1.1 tsubai return args.handle;
223 1.1 tsubai }
224 1.1 tsubai
225 1.15 perry static inline int
226 1.17 dsl OF_read(int handle, void *addr, int len)
227 1.1 tsubai {
228 1.1 tsubai static struct {
229 1.1 tsubai char *name;
230 1.1 tsubai int nargs;
231 1.1 tsubai int nreturns;
232 1.1 tsubai int ihandle;
233 1.1 tsubai void *addr;
234 1.1 tsubai int len;
235 1.1 tsubai int actual;
236 1.1 tsubai } args = {
237 1.1 tsubai "read",
238 1.1 tsubai 3,
239 1.1 tsubai 1,
240 1.1 tsubai };
241 1.1 tsubai
242 1.1 tsubai args.ihandle = handle;
243 1.1 tsubai args.addr = addr;
244 1.1 tsubai args.len = len;
245 1.1 tsubai openfirmware(&args);
246 1.1 tsubai
247 1.1 tsubai return args.actual;
248 1.1 tsubai }
249 1.1 tsubai
250 1.15 perry static inline int
251 1.17 dsl OF_seek(int handle, u_quad_t pos)
252 1.1 tsubai {
253 1.1 tsubai static struct {
254 1.1 tsubai char *name;
255 1.1 tsubai int nargs;
256 1.1 tsubai int nreturns;
257 1.1 tsubai int handle;
258 1.1 tsubai int poshi;
259 1.1 tsubai int poslo;
260 1.1 tsubai int status;
261 1.1 tsubai } args = {
262 1.1 tsubai "seek",
263 1.1 tsubai 3,
264 1.1 tsubai 1,
265 1.1 tsubai };
266 1.1 tsubai
267 1.1 tsubai args.handle = handle;
268 1.1 tsubai args.poshi = (int)(pos >> 32);
269 1.1 tsubai args.poslo = (int)pos;
270 1.1 tsubai openfirmware(&args);
271 1.1 tsubai
272 1.1 tsubai return args.status;
273 1.1 tsubai }
274 1.1 tsubai
275 1.15 perry static inline int
276 1.17 dsl OF_write(int handle, const void *addr, int len)
277 1.8 lukem {
278 1.8 lukem static struct {
279 1.8 lukem char *name;
280 1.8 lukem int nargs;
281 1.8 lukem int nreturns;
282 1.8 lukem int ihandle;
283 1.11 matt const void *addr;
284 1.8 lukem int len;
285 1.8 lukem int actual;
286 1.8 lukem } args = {
287 1.8 lukem "write",
288 1.8 lukem 3,
289 1.8 lukem 1,
290 1.8 lukem };
291 1.8 lukem
292 1.8 lukem args.ihandle = handle;
293 1.8 lukem args.addr = addr;
294 1.8 lukem args.len = len;
295 1.8 lukem openfirmware(&args);
296 1.8 lukem
297 1.8 lukem return args.actual;
298 1.8 lukem }
299 1.8 lukem
300 1.8 lukem int stdout;
301 1.8 lukem
302 1.8 lukem void
303 1.8 lukem putstrn(const char *s, size_t n)
304 1.8 lukem {
305 1.8 lukem OF_write(stdout, s, n);
306 1.8 lukem }
307 1.8 lukem
308 1.8 lukem #define putstr(x) putstrn((x),sizeof(x)-1)
309 1.8 lukem #define putc(x) do { char __x = (x) ; putstrn(&__x, 1); } while (0)
310 1.8 lukem
311 1.8 lukem
312 1.1 tsubai void
313 1.18 dsl startup(int arg1, int arg2, void *openfirm)
314 1.1 tsubai {
315 1.11 matt int fd, blk, chosen, options, j;
316 1.19 scole uint32_t cpuvers;
317 1.11 matt size_t i;
318 1.1 tsubai char *addr;
319 1.4 tsubai char bootpath[128];
320 1.4 tsubai
321 1.19 scole __asm volatile ("mfpvr %0" : "=r"(cpuvers));
322 1.19 scole cpuvers >>= 16;
323 1.19 scole
324 1.1 tsubai openfirmware = openfirm;
325 1.1 tsubai
326 1.1 tsubai chosen = OF_finddevice("/chosen");
327 1.4 tsubai if (OF_getprop(chosen, "bootpath", bootpath, sizeof(bootpath)) == 1) {
328 1.4 tsubai /*
329 1.4 tsubai * buggy firmware doesn't set bootpath...
330 1.4 tsubai */
331 1.4 tsubai options = OF_finddevice("/options");
332 1.4 tsubai OF_getprop(options, "boot-device", bootpath, sizeof(bootpath));
333 1.4 tsubai }
334 1.8 lukem if (OF_getprop(chosen, "stdout", &stdout, sizeof(stdout))
335 1.8 lukem != sizeof(stdout))
336 1.8 lukem stdout = -1;
337 1.1 tsubai
338 1.1 tsubai /*
339 1.1 tsubai * "scsi/sd@0:0" --> "scsi/sd@0"
340 1.1 tsubai */
341 1.8 lukem for (i = 0; i < sizeof(bootpath); i++) {
342 1.1 tsubai if (bootpath[i] == ':')
343 1.1 tsubai bootpath[i] = 0;
344 1.8 lukem if (bootpath[i] == 0)
345 1.8 lukem break;
346 1.8 lukem }
347 1.1 tsubai
348 1.9 lukem putstr("\r\nOF_open bootpath=");
349 1.8 lukem putstrn(bootpath, i);
350 1.1 tsubai fd = OF_open(bootpath);
351 1.1 tsubai
352 1.2 tsubai addr = (char *)entry_point;
353 1.8 lukem putstr("\r\nread stage 2 blocks: ");
354 1.11 matt for (j = 0; j < bbinfo.bbi_block_count; j++) {
355 1.11 matt if ((blk = bbinfo.bbi_block_table[j]) == 0)
356 1.6 lukem break;
357 1.11 matt putc('0' + j % 10);
358 1.1 tsubai OF_seek(fd, (u_quad_t)blk * 512);
359 1.6 lukem OF_read(fd, addr, bbinfo.bbi_block_size);
360 1.6 lukem addr += bbinfo.bbi_block_size;
361 1.1 tsubai }
362 1.8 lukem putstr(". done!\r\nstarting stage 2...\r\n");
363 1.1 tsubai
364 1.19 scole if (cpuvers != MPC601) {
365 1.19 scole /*
366 1.19 scole * enable D/I cache
367 1.19 scole */
368 1.19 scole __asm(
369 1.19 scole "mtdbatu 3,%0\n\t"
370 1.19 scole "mtdbatl 3,%1\n\t"
371 1.19 scole "mtibatu 3,%0\n\t"
372 1.19 scole "mtibatl 3,%1\n\t"
373 1.19 scole "isync"
374 1.19 scole :: "r"(BATU(0, BAT_BL_256M, BAT_Vs)),
375 1.19 scole "r"(BATL(0, 0, BAT_PP_RW)));
376 1.19 scole }
377 1.1 tsubai
378 1.2 tsubai entry_point(0, 0, openfirm);
379 1.4 tsubai for (;;); /* just in case */
380 1.1 tsubai }
381