File: /usr/src/linux/arch/ppc/boot/pmac/start.c
1 /*
2 * BK Id: SCCS/s.start.c 1.10 07/25/01 18:13:07 trini
3 */
4 /*
5 * Copyright (C) Paul Mackerras 1997.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version.
11 */
12 #include <stdarg.h>
13
14 extern int strlen(const char *s);
15 extern void boot(int a1, int a2, void *prom);
16
17 int (*prom)();
18
19 void *chosen_handle;
20 void *stdin;
21 void *stdout;
22 void *stderr;
23
24 void exit(void);
25 void *finddevice(const char *name);
26 int getprop(void *phandle, const char *name, void *buf, int buflen);
27 void printk(char *fmt, ...);
28
29 void
30 start(int a1, int a2, void *promptr)
31 {
32 prom = (int (*)()) promptr;
33 chosen_handle = finddevice("/chosen");
34 if (chosen_handle == (void *) -1)
35 exit();
36 if (getprop(chosen_handle, "stdout", &stdout, sizeof(stdout)) != 4)
37 exit();
38 stderr = stdout;
39 if (getprop(chosen_handle, "stdin", &stdin, sizeof(stdin)) != 4)
40 exit();
41
42 boot(a1, a2, promptr);
43 for (;;)
44 exit();
45 }
46
47 int
48 write(void *handle, void *ptr, int nb)
49 {
50 struct prom_args {
51 char *service;
52 int nargs;
53 int nret;
54 void *ihandle;
55 void *addr;
56 int len;
57 int actual;
58 } args;
59
60 args.service = "write";
61 args.nargs = 3;
62 args.nret = 1;
63 args.ihandle = handle;
64 args.addr = ptr;
65 args.len = nb;
66 args.actual = -1;
67 (*prom)(&args);
68 return args.actual;
69 }
70
71 int writestring(void *f, char *ptr, int nb)
72 {
73 int w = 0, i;
74 char *ret = "\r";
75
76 for (i = 0; i < nb; ++i) {
77 if (ptr[i] == '\n') {
78 if (i > w) {
79 write(f, ptr + w, i - w);
80 w = i;
81 }
82 write(f, ret, 1);
83 }
84 }
85 if (w < nb)
86 write(f, ptr + w, nb - w);
87 return nb;
88 }
89
90 int
91 read(void *handle, void *ptr, int nb)
92 {
93 struct prom_args {
94 char *service;
95 int nargs;
96 int nret;
97 void *ihandle;
98 void *addr;
99 int len;
100 int actual;
101 } args;
102
103 args.service = "read";
104 args.nargs = 3;
105 args.nret = 1;
106 args.ihandle = handle;
107 args.addr = ptr;
108 args.len = nb;
109 args.actual = -1;
110 (*prom)(&args);
111 return args.actual;
112 }
113
114 void
115 exit(void)
116 {
117 struct prom_args {
118 char *service;
119 } args;
120
121 for (;;) {
122 args.service = "exit";
123 (*prom)(&args);
124 }
125 }
126
127 void
128 pause(void)
129 {
130 struct prom_args {
131 char *service;
132 } args;
133
134 args.service = "enter";
135 (*prom)(&args);
136 }
137
138 void *
139 finddevice(const char *name)
140 {
141 struct prom_args {
142 char *service;
143 int nargs;
144 int nret;
145 const char *devspec;
146 void *phandle;
147 } args;
148
149 args.service = "finddevice";
150 args.nargs = 1;
151 args.nret = 1;
152 args.devspec = name;
153 args.phandle = (void *) -1;
154 (*prom)(&args);
155 return args.phandle;
156 }
157
158 void *
159 claim(unsigned int virt, unsigned int size, unsigned int align)
160 {
161 struct prom_args {
162 char *service;
163 int nargs;
164 int nret;
165 unsigned int virt;
166 unsigned int size;
167 unsigned int align;
168 void *ret;
169 } args;
170
171 args.service = "claim";
172 args.nargs = 3;
173 args.nret = 1;
174 args.virt = virt;
175 args.size = size;
176 args.align = align;
177 (*prom)(&args);
178 return args.ret;
179 }
180
181 void
182 release(void *virt, unsigned int size)
183 {
184 struct prom_args {
185 char *service;
186 int nargs;
187 int nret;
188 void *virt;
189 unsigned int size;
190 } args;
191
192 args.service = "release";
193 args.nargs = 2;
194 args.nret = 0;
195 args.virt = virt;
196 args.size = size;
197 (*prom)(&args);
198 }
199
200 int
201 getprop(void *phandle, const char *name, void *buf, int buflen)
202 {
203 struct prom_args {
204 char *service;
205 int nargs;
206 int nret;
207 void *phandle;
208 const char *name;
209 void *buf;
210 int buflen;
211 int size;
212 } args;
213
214 args.service = "getprop";
215 args.nargs = 4;
216 args.nret = 1;
217 args.phandle = phandle;
218 args.name = name;
219 args.buf = buf;
220 args.buflen = buflen;
221 args.size = -1;
222 (*prom)(&args);
223 return args.size;
224 }
225
226 int
227 putc(int c, void *f)
228 {
229 char ch = c;
230
231 return writestring(f, &ch, 1) == 1? c: -1;
232 }
233
234 int
235 putchar(int c)
236 {
237 return putc(c, stdout);
238 }
239
240 int
241 fputs(char *str, void *f)
242 {
243 int n = strlen(str);
244
245 return writestring(f, str, n) == n? 0: -1;
246 }
247
248 int
249 readchar(void)
250 {
251 char ch;
252
253 for (;;) {
254 switch (read(stdin, &ch, 1)) {
255 case 1:
256 return ch;
257 case -1:
258 printk("read(stdin) returned -1\n");
259 return -1;
260 }
261 }
262 }
263
264 static char line[256];
265 static char *lineptr;
266 static int lineleft;
267
268 int
269 getchar(void)
270 {
271 int c;
272
273 if (lineleft == 0) {
274 lineptr = line;
275 for (;;) {
276 c = readchar();
277 if (c == -1 || c == 4)
278 break;
279 if (c == '\r' || c == '\n') {
280 *lineptr++ = '\n';
281 putchar('\n');
282 break;
283 }
284 switch (c) {
285 case 0177:
286 case '\b':
287 if (lineptr > line) {
288 putchar('\b');
289 putchar(' ');
290 putchar('\b');
291 --lineptr;
292 }
293 break;
294 case 'U' & 0x1F:
295 while (lineptr > line) {
296 putchar('\b');
297 putchar(' ');
298 putchar('\b');
299 --lineptr;
300 }
301 break;
302 default:
303 if (lineptr >= &line[sizeof(line) - 1])
304 putchar('\a');
305 else {
306 putchar(c);
307 *lineptr++ = c;
308 }
309 }
310 }
311 lineleft = lineptr - line;
312 lineptr = line;
313 }
314 if (lineleft == 0)
315 return -1;
316 --lineleft;
317 return *lineptr++;
318 }
319
320 extern int vsprintf(char *buf, const char *fmt, va_list args);
321 static char sprint_buf[1024];
322
323 void
324 printk(char *fmt, ...)
325 {
326 va_list args;
327 int n;
328
329 va_start(args, fmt);
330 n = vsprintf(sprint_buf, fmt, args);
331 va_end(args);
332 writestring(stdout, sprint_buf, n);
333 }
334
335 int
336 printf(char *fmt, ...)
337 {
338 va_list args;
339 int n;
340
341 va_start(args, fmt);
342 n = vsprintf(sprint_buf, fmt, args);
343 va_end(args);
344 writestring(stdout, sprint_buf, n);
345 return n;
346 }
347