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
12static int (*gCallOpenFirmware)(void *) = 0;
13int gChosen;
14
15
16status_t
17of_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
29int
30of_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
72int
73of_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
122int
123of_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
173int
174of_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
194int
195of_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
215int
216of_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
236int
237of_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
254int
255of_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
274int
275of_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
292int
293of_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
313int
314of_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
334int
335of_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
353int
354of_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
373int
374of_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
396int
397of_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
414void
415of_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
428int
429of_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
448int
449of_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
468int
469of_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
490int
491of_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
505void *
506of_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
531int
532of_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
552int
553of_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
569void
570of_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