bootxx.c revision 1.4 1 /* $NetBSD: bootxx.c,v 1.4 1998/07/13 17:35:55 tsubai 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 <machine/bat.h>
36
37 int (*openfirmware)(void *);
38 int stack[1024];
39
40 #define MAXBLOCKNUM 30
41
42 void (*entry_point)(int, int, void *) = (void *)0;
43 int block_size = 0;
44 int block_count = MAXBLOCKNUM;
45 int block_table[MAXBLOCKNUM] = { 0 };
46
47 asm("
48 .text
49 .align 2
50 .globl _start
51 _start:
52
53 li 8,0x4000 /* _start */
54 li 9,0x20
55 mtctr 9
56 1:
57 dcbf 0,8
58 icbi 0,8
59 addi 8,8,0x20
60 bdnz 1b
61 sync
62
63 li 0,0
64 mtdbatu 3,0
65 mtibatu 3,0
66 isync
67 li 8,0x1ffe /* map the lowest 256MB */
68 li 9,0x22 /* BAT_I */
69 mtdbatl 3,9
70 mtdbatu 3,8
71 mtibatl 3,9
72 mtibatu 3,8
73 isync
74
75 li 1,(stack+4096)@l /* setup 4KB of stack */
76
77 b startup
78 ");
79
80
81 static __inline int
82 OF_finddevice(name)
83 char *name;
84 {
85 static struct {
86 char *name;
87 int nargs;
88 int nreturns;
89 char *device;
90 int phandle;
91 } args = {
92 "finddevice",
93 1,
94 1,
95 };
96
97 args.device = name;
98 openfirmware(&args);
99
100 return args.phandle;
101 }
102
103 static __inline int
104 OF_getprop(handle, prop, buf, buflen)
105 int handle;
106 char *prop;
107 void *buf;
108 int buflen;
109 {
110 static struct {
111 char *name;
112 int nargs;
113 int nreturns;
114 int phandle;
115 char *prop;
116 void *buf;
117 int buflen;
118 int size;
119 } args = {
120 "getprop",
121 4,
122 1,
123 };
124
125 args.phandle = handle;
126 args.prop = prop;
127 args.buf = buf;
128 args.buflen = buflen;
129 openfirmware(&args);
130
131 return args.size;
132 }
133
134 static __inline int
135 OF_open(dname)
136 char *dname;
137 {
138 static struct {
139 char *name;
140 int nargs;
141 int nreturns;
142 char *dname;
143 int handle;
144 } args = {
145 "open",
146 1,
147 1,
148 };
149
150 args.dname = dname;
151 openfirmware(&args);
152
153 return args.handle;
154 }
155
156 static __inline int
157 OF_read(handle, addr, len)
158 int handle;
159 void *addr;
160 int len;
161 {
162 static struct {
163 char *name;
164 int nargs;
165 int nreturns;
166 int ihandle;
167 void *addr;
168 int len;
169 int actual;
170 } args = {
171 "read",
172 3,
173 1,
174 };
175
176 args.ihandle = handle;
177 args.addr = addr;
178 args.len = len;
179 openfirmware(&args);
180
181 return args.actual;
182 }
183
184 static __inline int
185 OF_seek(handle, pos)
186 int handle;
187 u_quad_t pos;
188 {
189 static struct {
190 char *name;
191 int nargs;
192 int nreturns;
193 int handle;
194 int poshi;
195 int poslo;
196 int status;
197 } args = {
198 "seek",
199 3,
200 1,
201 };
202
203 args.handle = handle;
204 args.poshi = (int)(pos >> 32);
205 args.poslo = (int)pos;
206 openfirmware(&args);
207
208 return args.status;
209 }
210
211 void
212 startup(arg1, arg2, openfirm)
213 int arg1, arg2;
214 void *openfirm;
215 {
216 int fd, blk, chosen, options;
217 int i, bs;
218 char *addr;
219 char bootpath[128];
220
221 openfirmware = openfirm;
222
223 chosen = OF_finddevice("/chosen");
224 if (OF_getprop(chosen, "bootpath", bootpath, sizeof(bootpath)) == 1) {
225 /*
226 * buggy firmware doesn't set bootpath...
227 */
228 options = OF_finddevice("/options");
229 OF_getprop(options, "boot-device", bootpath, sizeof(bootpath));
230 }
231
232 /*
233 * "scsi/sd@0:0" --> "scsi/sd@0"
234 */
235 for (i = 0; i < sizeof(bootpath); i++)
236 if (bootpath[i] == ':')
237 bootpath[i] = 0;
238
239 fd = OF_open(bootpath);
240
241 addr = (char *)entry_point;
242 bs = block_size;
243 for (i = 0; i < block_count; i++) {
244 blk = block_table[i];
245
246 OF_seek(fd, (u_quad_t)blk * 512);
247 OF_read(fd, addr, bs);
248 addr += bs;
249 }
250
251 /*
252 * enable D/I cache
253 */
254 asm("
255 mtdbatu 3,%0
256 mtdbatl 3,%1
257 mtibatu 3,%0
258 mtibatl 3,%1
259 isync
260 " :: "r"(BATU(0)), "r"(BATL(0, 0)));
261
262 entry_point(0, 0, openfirm);
263 for (;;); /* just in case */
264 }
265