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