xref: /haiku/src/system/kernel/platform/openfirmware/openfirmware.cpp (revision 220d04022750f40f8bac8f01fa551211e28d04f2)
1 /*
2  * Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 #include <platform/openfirmware/openfirmware.h>
7 
8 #include <stdarg.h>
9 
10 
11 // OpenFirmware entry function
12 static int (*gCallOpenFirmware)(void *) = 0;
13 int gChosen;
14 
15 
16 status_t
17 of_init(int (*openFirmwareEntry)(void *))
18 {
19 	gCallOpenFirmware = openFirmwareEntry;
20 
21 	gChosen = of_finddevice("/chosen");
22 	if (gChosen == OF_FAILED)
23 		return B_ERROR;
24 
25 	return B_OK;
26 }
27 
28 
29 int
30 of_call_client_function(const char *method, int numArgs, int numReturns, ...)
31 {
32 	struct {
33 		const char	*name;
34 		int			num_args;
35 		int			num_returns;
36 		void		*args[10];
37 	} args = {method, numArgs, numReturns};
38 	va_list list;
39 	int i;
40 
41 	// iterate over all arguments and copy them into the
42 	// structure passed over to the OpenFirmware
43 
44 	va_start(list, numReturns);
45 	for (i = 0; i < numArgs; i++) {
46 		// copy args
47 		args.args[i] = (void *)va_arg(list, void *);
48 	}
49 	for (i = numArgs; i < numArgs + numReturns; i++) {
50 		// clear return values
51 		args.args[i] = NULL;
52 	}
53 
54 	if (gCallOpenFirmware(&args) == OF_FAILED)
55 		return OF_FAILED;
56 
57 	if (numReturns > 0) {
58 		// copy return values over to the provided location
59 
60 		for (i = numArgs; i < numArgs + numReturns; i++) {
61 			void **store = va_arg(list, void **);
62 			if (store)
63 				*store = args.args[i];
64 		}
65 	}
66 	va_end(list);
67 
68 	return 0;
69 }
70 
71 
72 int
73 of_interpret(const char *command, int numArgs, int numReturns, ...)
74 {
75 	struct {
76 		const char	*name;
77 		int			num_args;
78 		int			num_returns;
79 			// "IN:	[string] cmd, stack_arg1, ..., stack_argP
80 			// OUT:	catch-result, stack_result1, ..., stack_resultQ
81 			// [...]
82 			// An implementation shall allow at least six stack_arg and six
83 			// stack_result items."
84 		const char	*command;
85 		void		*args[13];
86 	} args = {"interpret", numArgs + 1, numReturns + 1, command};
87 	va_list list;
88 	int i;
89 
90 	// iterate over all arguments and copy them into the
91 	// structure passed over to the OpenFirmware
92 
93 	va_start(list, numReturns);
94 	for (i = 0; i < numArgs; i++) {
95 		// copy args
96 		args.args[i] = (void *)va_arg(list, void *);
97 	}
98 	for (i = numArgs; i < numArgs + numReturns + 1; i++) {
99 		// clear return values
100 		args.args[i] = NULL;
101 	}
102 
103 	// args.args[numArgs] is the "catch-result" return value
104 	if (gCallOpenFirmware(&args) == OF_FAILED || args.args[numArgs])
105 		return OF_FAILED;
106 
107 	if (numReturns > 0) {
108 		// copy return values over to the provided location
109 
110 		for (i = numArgs + 1; i < numArgs + 1 + numReturns; i++) {
111 			void **store = va_arg(list, void **);
112 			if (store)
113 				*store = args.args[i];
114 		}
115 	}
116 	va_end(list);
117 
118 	return 0;
119 }
120 
121 
122 int
123 of_call_method(int handle, const char *method, int numArgs, int numReturns, ...)
124 {
125 	struct {
126 		const char	*name;
127 		int			num_args;
128 		int			num_returns;
129 			// "IN:	[string] method, ihandle, stack_arg1, ..., stack_argP
130 			// OUT:	catch-result, stack_result1, ..., stack_resultQ
131 			// [...]
132 			// An implementation shall allow at least six stack_arg and six
133 			// stack_result items."
134 		const char	*method;
135 		int			handle;
136 		void		*args[13];
137 	} args = {"call-method", numArgs + 2, numReturns + 1, method, handle};
138 	va_list list;
139 	int i;
140 
141 	// iterate over all arguments and copy them into the
142 	// structure passed over to the OpenFirmware
143 
144 	va_start(list, numReturns);
145 	for (i = 0; i < numArgs; i++) {
146 		// copy args
147 		args.args[i] = (void *)va_arg(list, void *);
148 	}
149 	for (i = numArgs; i < numArgs + numReturns + 1; i++) {
150 		// clear return values
151 		args.args[i] = NULL;
152 	}
153 
154 	// args.args[numArgs] is the "catch-result" return value
155 	if (gCallOpenFirmware(&args) == OF_FAILED || args.args[numArgs])
156 		return OF_FAILED;
157 
158 	if (numReturns > 0) {
159 		// copy return values over to the provided location
160 
161 		for (i = numArgs + 1; i < numArgs + 1 + numReturns; i++) {
162 			void **store = va_arg(list, void **);
163 			if (store)
164 				*store = args.args[i];
165 		}
166 	}
167 	va_end(list);
168 
169 	return 0;
170 }
171 
172 
173 int
174 of_finddevice(const char *device)
175 {
176 	struct {
177 		const char	*name;
178 		int			num_args;
179 		int			num_returns;
180 		const char	*device;
181 		int			handle;
182 	} args = {"finddevice", 1, 1, device, 0};
183 
184 	if (gCallOpenFirmware(&args) == OF_FAILED)
185 		return OF_FAILED;
186 
187 	return args.handle;
188 }
189 
190 
191 /** Returns the first child of the given node
192  */
193 
194 int
195 of_child(int node)
196 {
197 	struct {
198 		const char	*name;
199 		int			num_args;
200 		int			num_returns;
201 		int			node;
202 		int			child;
203 	} args = {"child", 1, 1, node, 0};
204 
205 	if (gCallOpenFirmware(&args) == OF_FAILED)
206 		return OF_FAILED;
207 
208 	return args.child;
209 }
210 
211 
212 /** Returns the next sibling of the given node
213  */
214 
215 int
216 of_peer(int node)
217 {
218 	struct {
219 		const char	*name;
220 		int			num_args;
221 		int			num_returns;
222 		int			node;
223 		int			next_sibling;
224 	} args = {"peer", 1, 1, node, 0};
225 
226 	if (gCallOpenFirmware(&args) == OF_FAILED)
227 		return OF_FAILED;
228 
229 	return args.next_sibling;
230 }
231 
232 
233 /** Returns the parent of the given node
234  */
235 
236 int
237 of_parent(int node)
238 {
239 	struct {
240 		const char	*name;
241 		int			num_args;
242 		int			num_returns;
243 		int			node;
244 		int			parent;
245 	} args = {"parent", 1, 1, node, 0};
246 
247 	if (gCallOpenFirmware(&args) == OF_FAILED)
248 		return OF_FAILED;
249 
250 	return args.parent;
251 }
252 
253 
254 int
255 of_instance_to_path(int instance, char *pathBuffer, int bufferSize)
256 {
257 	struct {
258 		const char	*name;
259 		int			num_args;
260 		int			num_returns;
261 		int			instance;
262 		char		*path_buffer;
263 		int			buffer_size;
264 		int			size;
265 	} args = {"instance-to-path", 3, 1, instance, pathBuffer, bufferSize, 0};
266 
267 	if (gCallOpenFirmware(&args) == OF_FAILED)
268 		return OF_FAILED;
269 
270 	return args.size;
271 }
272 
273 
274 int
275 of_instance_to_package(int instance)
276 {
277 	struct {
278 		const char	*name;
279 		int			num_args;
280 		int			num_returns;
281 		int			instance;
282 		int			package;
283 	} args = {"instance-to-package", 1, 1, instance, 0};
284 
285 	if (gCallOpenFirmware(&args) == OF_FAILED)
286 		return OF_FAILED;
287 
288 	return args.package;
289 }
290 
291 
292 int
293 of_getprop(int package, const char *property, void *buffer, int bufferSize)
294 {
295 	struct {
296 		const char	*name;
297 		int			num_args;
298 		int			num_returns;
299 		int			package;
300 		const char	*property;
301 		void		*buffer;
302 		int			buffer_size;
303 		int			size;
304 	} args = {"getprop", 4, 1, package, property, buffer, bufferSize, 0};
305 
306 	if (gCallOpenFirmware(&args) == OF_FAILED)
307 		return OF_FAILED;
308 
309 	return args.size;
310 }
311 
312 
313 int
314 of_setprop(int package, const char *property, const void *buffer, int bufferSize)
315 {
316 	struct {
317 		const char	*name;
318 		int			num_args;
319 		int			num_returns;
320 		int			package;
321 		const char	*property;
322 		const void	*buffer;
323 		int			buffer_size;
324 		int			size;
325 	} args = {"setprop", 4, 1, package, property, buffer, bufferSize, 0};
326 
327 	if (gCallOpenFirmware(&args) == OF_FAILED)
328 		return OF_FAILED;
329 
330 	return args.size;
331 }
332 
333 
334 int
335 of_getproplen(int package, const char *property)
336 {
337 	struct {
338 		const char	*name;
339 		int			num_args;
340 		int			num_returns;
341 		int			package;
342 		const char	*property;
343 		int			size;
344 	} args = {"getproplen", 2, 1, package, property, 0};
345 
346 	if (gCallOpenFirmware(&args) == OF_FAILED)
347 		return OF_FAILED;
348 
349 	return args.size;
350 }
351 
352 
353 int
354 of_nextprop(int package, const char *previousProperty, char *nextProperty)
355 {
356 	struct {
357 		const char	*name;
358 		int			num_args;
359 		int			num_returns;
360 		int			package;
361 		const char	*previous_property;
362 		char		*next_property;
363 		int			flag;
364 	} args = {"nextprop", 3, 1, package, previousProperty, nextProperty, 0};
365 
366 	if (gCallOpenFirmware(&args) == OF_FAILED)
367 		return OF_FAILED;
368 
369 	return args.flag;
370 }
371 
372 
373 int
374 of_package_to_path(int package, char *pathBuffer, int bufferSize)
375 {
376 	struct {
377 		const char	*name;
378 		int			num_args;
379 		int			num_returns;
380 		int			package;
381 		char		*path_buffer;
382 		int			buffer_size;
383 		int			size;
384 	} args = {"package-to-path", 3, 1, package, pathBuffer, bufferSize, 0};
385 
386 	if (gCallOpenFirmware(&args) == OF_FAILED)
387 		return OF_FAILED;
388 
389 	return args.size;
390 }
391 
392 
393 //	I/O functions
394 
395 
396 int
397 of_open(const char *nodeName)
398 {
399 	struct {
400 		const char	*name;
401 		int			num_args;
402 		int			num_returns;
403 		const char	*node_name;
404 		int			handle;
405 	} args = {"open", 1, 1, nodeName, 0};
406 
407 	if (gCallOpenFirmware(&args) == OF_FAILED || args.handle == 0)
408 		return OF_FAILED;
409 
410 	return args.handle;
411 }
412 
413 
414 void
415 of_close(int handle)
416 {
417 	struct {
418 		const char	*name;
419 		int			num_args;
420 		int			num_returns;
421 		int			handle;
422 	} args = {"close", 1, 0, handle};
423 
424 	gCallOpenFirmware(&args);
425 }
426 
427 
428 int
429 of_read(int handle, void *buffer, int bufferSize)
430 {
431 	struct {
432 		const char	*name;
433 		int			num_args;
434 		int			num_returns;
435 		int			handle;
436 		void		*buffer;
437 		int			buffer_size;
438 		int			size;
439 	} args = {"read", 3, 1, handle, buffer, bufferSize, 0};
440 
441 	if (gCallOpenFirmware(&args) == OF_FAILED)
442 		return OF_FAILED;
443 
444 	return args.size;
445 }
446 
447 
448 int
449 of_write(int handle, const void *buffer, int bufferSize)
450 {
451 	struct {
452 		const char	*name;
453 		int			num_args;
454 		int			num_returns;
455 		int			handle;
456 		const void	*buffer;
457 		int			buffer_size;
458 		int			size;
459 	} args = {"write", 3, 1, handle, buffer, bufferSize, 0};
460 
461 	if (gCallOpenFirmware(&args) == OF_FAILED)
462 		return OF_FAILED;
463 
464 	return args.size;
465 }
466 
467 
468 int
469 of_seek(int handle, long long pos)
470 {
471 	struct {
472 		const char	*name;
473 		int			num_args;
474 		int			num_returns;
475 		int			handle;
476 		int64		pos;
477 		int			status;
478 	} args = {"seek", 3, 1, handle, pos, 0};
479 
480 	if (gCallOpenFirmware(&args) == OF_FAILED)
481 		return OF_FAILED;
482 
483 	return args.status;
484 }
485 
486 
487 // memory functions
488 
489 
490 int
491 of_release(void *virtualAddress, int size)
492 {
493 	struct {
494 		const char *name;
495 		int			num_args;
496 		int			num_returns;
497 		void		*virtualAddress;
498 		int			size;
499 	} args = {"release", 2, 0, virtualAddress, size};
500 
501 	return gCallOpenFirmware(&args);
502 }
503 
504 
505 void *
506 of_claim(void *virtualAddress, int size, int align)
507 {
508 	struct {
509 		const char	*name;
510 		int			num_args;
511 		int			num_returns;
512 		void		*virtualAddress;
513 		int			size;
514 		int			align;
515 		void		*address;
516 	} args = {"claim", 3, 1, virtualAddress, size, align};
517 
518 	if (gCallOpenFirmware(&args) == OF_FAILED)
519 		return NULL;
520 
521 	return args.address;
522 }
523 
524 
525 // misc functions
526 
527 
528 /** tests if the given service is missing
529  */
530 
531 int
532 of_test(const char *service)
533 {
534 	struct {
535 		const char	*name;
536 		int			num_args;
537 		int			num_returns;
538 		const char	*service;
539 		int			missing;
540 	} args = {"test", 1, 1, service, 0};
541 
542 	if (gCallOpenFirmware(&args) == OF_FAILED)
543 		return OF_FAILED;
544 
545 	return args.missing;
546 }
547 
548 
549 /** Returns the millisecond counter
550  */
551 
552 int
553 of_milliseconds(void)
554 {
555 	struct {
556 		const char	*name;
557 		int			num_args;
558 		int			num_returns;
559 		int			milliseconds;
560 	} args = {"milliseconds", 0, 1, 0};
561 
562 	if (gCallOpenFirmware(&args) == OF_FAILED)
563 		return OF_FAILED;
564 
565 	return args.milliseconds;
566 }
567 
568 
569 void
570 of_exit(void)
571 {
572 	struct {
573 		const char	*name;
574 		int			num_args;
575 		int			num_returns;
576 	} args = {"exit", 0, 0};
577 
578 	gCallOpenFirmware(&args);
579 }
580 
581