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