xref: /openbmc/u-boot/api/api.c (revision e8f80a5a)
1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
2500856ebSRafal Jaworowski /*
3500856ebSRafal Jaworowski  * (C) Copyright 2007 Semihalf
4500856ebSRafal Jaworowski  *
5500856ebSRafal Jaworowski  * Written by: Rafal Jaworowski <raj@semihalf.com>
6500856ebSRafal Jaworowski  */
7500856ebSRafal Jaworowski 
8500856ebSRafal Jaworowski #include <config.h>
9500856ebSRafal Jaworowski #include <command.h>
10500856ebSRafal Jaworowski #include <common.h>
11500856ebSRafal Jaworowski #include <malloc.h>
12a8409f4fSWolfgang Denk #include <environment.h>
13500856ebSRafal Jaworowski #include <linux/types.h>
14500856ebSRafal Jaworowski #include <api_public.h>
15500856ebSRafal Jaworowski 
16500856ebSRafal Jaworowski #include "api_private.h"
17500856ebSRafal Jaworowski 
18500856ebSRafal Jaworowski #define DEBUG
19500856ebSRafal Jaworowski #undef DEBUG
20500856ebSRafal Jaworowski 
21500856ebSRafal Jaworowski /*****************************************************************************
22500856ebSRafal Jaworowski  *
23500856ebSRafal Jaworowski  * This is the API core.
24500856ebSRafal Jaworowski  *
25500856ebSRafal Jaworowski  * API_ functions are part of U-Boot code and constitute the lowest level
26500856ebSRafal Jaworowski  * calls:
27500856ebSRafal Jaworowski  *
28500856ebSRafal Jaworowski  *  - they know what values they need as arguments
29500856ebSRafal Jaworowski  *  - their direct return value pertains to the API_ "shell" itself (0 on
30500856ebSRafal Jaworowski  *    success, some error code otherwise)
31500856ebSRafal Jaworowski  *  - if the call returns a value it is buried within arguments
32500856ebSRafal Jaworowski  *
33500856ebSRafal Jaworowski  ****************************************************************************/
34500856ebSRafal Jaworowski 
35500856ebSRafal Jaworowski #ifdef DEBUG
36500856ebSRafal Jaworowski #define debugf(fmt, args...) do { printf("%s(): ", __func__); printf(fmt, ##args); } while (0)
37500856ebSRafal Jaworowski #else
38500856ebSRafal Jaworowski #define debugf(fmt, args...)
39500856ebSRafal Jaworowski #endif
40500856ebSRafal Jaworowski 
41500856ebSRafal Jaworowski typedef	int (*cfp_t)(va_list argp);
42500856ebSRafal Jaworowski 
43500856ebSRafal Jaworowski static int calls_no;
44500856ebSRafal Jaworowski 
45500856ebSRafal Jaworowski /*
46500856ebSRafal Jaworowski  * pseudo signature:
47500856ebSRafal Jaworowski  *
48500856ebSRafal Jaworowski  * int API_getc(int *c)
49500856ebSRafal Jaworowski  */
API_getc(va_list ap)50500856ebSRafal Jaworowski static int API_getc(va_list ap)
51500856ebSRafal Jaworowski {
52500856ebSRafal Jaworowski 	int *c;
53500856ebSRafal Jaworowski 
5478757d52SStanislav Galabov 	if ((c = (int *)va_arg(ap, uintptr_t)) == NULL)
55500856ebSRafal Jaworowski 		return API_EINVAL;
56500856ebSRafal Jaworowski 
57500856ebSRafal Jaworowski 	*c = getc();
58500856ebSRafal Jaworowski 	return 0;
59500856ebSRafal Jaworowski }
60500856ebSRafal Jaworowski 
61500856ebSRafal Jaworowski /*
62500856ebSRafal Jaworowski  * pseudo signature:
63500856ebSRafal Jaworowski  *
64500856ebSRafal Jaworowski  * int API_tstc(int *c)
65500856ebSRafal Jaworowski  */
API_tstc(va_list ap)66500856ebSRafal Jaworowski static int API_tstc(va_list ap)
67500856ebSRafal Jaworowski {
68500856ebSRafal Jaworowski 	int *t;
69500856ebSRafal Jaworowski 
7078757d52SStanislav Galabov 	if ((t = (int *)va_arg(ap, uintptr_t)) == NULL)
71500856ebSRafal Jaworowski 		return API_EINVAL;
72500856ebSRafal Jaworowski 
73500856ebSRafal Jaworowski 	*t = tstc();
74500856ebSRafal Jaworowski 	return 0;
75500856ebSRafal Jaworowski }
76500856ebSRafal Jaworowski 
77500856ebSRafal Jaworowski /*
78500856ebSRafal Jaworowski  * pseudo signature:
79500856ebSRafal Jaworowski  *
80500856ebSRafal Jaworowski  * int API_putc(char *ch)
81500856ebSRafal Jaworowski  */
API_putc(va_list ap)82500856ebSRafal Jaworowski static int API_putc(va_list ap)
83500856ebSRafal Jaworowski {
84500856ebSRafal Jaworowski 	char *c;
85500856ebSRafal Jaworowski 
8678757d52SStanislav Galabov 	if ((c = (char *)va_arg(ap, uintptr_t)) == NULL)
87500856ebSRafal Jaworowski 		return API_EINVAL;
88500856ebSRafal Jaworowski 
89500856ebSRafal Jaworowski 	putc(*c);
90500856ebSRafal Jaworowski 	return 0;
91500856ebSRafal Jaworowski }
92500856ebSRafal Jaworowski 
93500856ebSRafal Jaworowski /*
94500856ebSRafal Jaworowski  * pseudo signature:
95500856ebSRafal Jaworowski  *
96500856ebSRafal Jaworowski  * int API_puts(char **s)
97500856ebSRafal Jaworowski  */
API_puts(va_list ap)98500856ebSRafal Jaworowski static int API_puts(va_list ap)
99500856ebSRafal Jaworowski {
100500856ebSRafal Jaworowski 	char *s;
101500856ebSRafal Jaworowski 
10278757d52SStanislav Galabov 	if ((s = (char *)va_arg(ap, uintptr_t)) == NULL)
103500856ebSRafal Jaworowski 		return API_EINVAL;
104500856ebSRafal Jaworowski 
105500856ebSRafal Jaworowski 	puts(s);
106500856ebSRafal Jaworowski 	return 0;
107500856ebSRafal Jaworowski }
108500856ebSRafal Jaworowski 
109500856ebSRafal Jaworowski /*
110500856ebSRafal Jaworowski  * pseudo signature:
111500856ebSRafal Jaworowski  *
112500856ebSRafal Jaworowski  * int API_reset(void)
113500856ebSRafal Jaworowski  */
API_reset(va_list ap)114500856ebSRafal Jaworowski static int API_reset(va_list ap)
115500856ebSRafal Jaworowski {
116500856ebSRafal Jaworowski 	do_reset(NULL, 0, 0, NULL);
117500856ebSRafal Jaworowski 
118500856ebSRafal Jaworowski 	/* NOT REACHED */
119500856ebSRafal Jaworowski 	return 0;
120500856ebSRafal Jaworowski }
121500856ebSRafal Jaworowski 
122500856ebSRafal Jaworowski /*
123500856ebSRafal Jaworowski  * pseudo signature:
124500856ebSRafal Jaworowski  *
125500856ebSRafal Jaworowski  * int API_get_sys_info(struct sys_info *si)
126500856ebSRafal Jaworowski  *
127500856ebSRafal Jaworowski  * fill out the sys_info struct containing selected parameters about the
128500856ebSRafal Jaworowski  * machine
129500856ebSRafal Jaworowski  */
API_get_sys_info(va_list ap)130500856ebSRafal Jaworowski static int API_get_sys_info(va_list ap)
131500856ebSRafal Jaworowski {
132500856ebSRafal Jaworowski 	struct sys_info *si;
133500856ebSRafal Jaworowski 
13478757d52SStanislav Galabov 	si = (struct sys_info *)va_arg(ap, uintptr_t);
135500856ebSRafal Jaworowski 	if (si == NULL)
136500856ebSRafal Jaworowski 		return API_ENOMEM;
137500856ebSRafal Jaworowski 
138500856ebSRafal Jaworowski 	return (platform_sys_info(si)) ? 0 : API_ENODEV;
139500856ebSRafal Jaworowski }
140500856ebSRafal Jaworowski 
141500856ebSRafal Jaworowski /*
142500856ebSRafal Jaworowski  * pseudo signature:
143500856ebSRafal Jaworowski  *
144500856ebSRafal Jaworowski  * int API_udelay(unsigned long *udelay)
145500856ebSRafal Jaworowski  */
API_udelay(va_list ap)146500856ebSRafal Jaworowski static int API_udelay(va_list ap)
147500856ebSRafal Jaworowski {
148500856ebSRafal Jaworowski 	unsigned long *d;
149500856ebSRafal Jaworowski 
15078757d52SStanislav Galabov 	if ((d = (unsigned long *)va_arg(ap, unsigned long)) == NULL)
151500856ebSRafal Jaworowski 		return API_EINVAL;
152500856ebSRafal Jaworowski 
153500856ebSRafal Jaworowski 	udelay(*d);
154500856ebSRafal Jaworowski 	return 0;
155500856ebSRafal Jaworowski }
156500856ebSRafal Jaworowski 
157500856ebSRafal Jaworowski /*
158500856ebSRafal Jaworowski  * pseudo signature:
159500856ebSRafal Jaworowski  *
160500856ebSRafal Jaworowski  * int API_get_timer(unsigned long *current, unsigned long *base)
161500856ebSRafal Jaworowski  */
API_get_timer(va_list ap)162500856ebSRafal Jaworowski static int API_get_timer(va_list ap)
163500856ebSRafal Jaworowski {
164500856ebSRafal Jaworowski 	unsigned long *base, *cur;
165500856ebSRafal Jaworowski 
16678757d52SStanislav Galabov 	cur = (unsigned long *)va_arg(ap, unsigned long);
167500856ebSRafal Jaworowski 	if (cur == NULL)
168500856ebSRafal Jaworowski 		return API_EINVAL;
169500856ebSRafal Jaworowski 
17078757d52SStanislav Galabov 	base = (unsigned long *)va_arg(ap, unsigned long);
171500856ebSRafal Jaworowski 	if (base == NULL)
172500856ebSRafal Jaworowski 		return API_EINVAL;
173500856ebSRafal Jaworowski 
174500856ebSRafal Jaworowski 	*cur = get_timer(*base);
175500856ebSRafal Jaworowski 	return 0;
176500856ebSRafal Jaworowski }
177500856ebSRafal Jaworowski 
178500856ebSRafal Jaworowski 
179500856ebSRafal Jaworowski /*****************************************************************************
180500856ebSRafal Jaworowski  *
181500856ebSRafal Jaworowski  * pseudo signature:
182500856ebSRafal Jaworowski  *
183500856ebSRafal Jaworowski  * int API_dev_enum(struct device_info *)
184500856ebSRafal Jaworowski  *
185500856ebSRafal Jaworowski  *
186500856ebSRafal Jaworowski  * cookies uniqely identify the previously enumerated device instance and
187500856ebSRafal Jaworowski  * provide a hint for what to inspect in current enum iteration:
188500856ebSRafal Jaworowski  *
189500856ebSRafal Jaworowski  *   - net: &eth_device struct address from list pointed to by eth_devices
190500856ebSRafal Jaworowski  *
1914101f687SSimon Glass  *   - storage: struct blk_desc struct address from &ide_dev_desc[n],
192500856ebSRafal Jaworowski  *     &scsi_dev_desc[n] and similar tables
193500856ebSRafal Jaworowski  *
194500856ebSRafal Jaworowski  ****************************************************************************/
195500856ebSRafal Jaworowski 
API_dev_enum(va_list ap)196500856ebSRafal Jaworowski static int API_dev_enum(va_list ap)
197500856ebSRafal Jaworowski {
198500856ebSRafal Jaworowski 	struct device_info *di;
199500856ebSRafal Jaworowski 
200500856ebSRafal Jaworowski 	/* arg is ptr to the device_info struct we are going to fill out */
20178757d52SStanislav Galabov 	di = (struct device_info *)va_arg(ap, uintptr_t);
202500856ebSRafal Jaworowski 	if (di == NULL)
203500856ebSRafal Jaworowski 		return API_EINVAL;
204500856ebSRafal Jaworowski 
205500856ebSRafal Jaworowski 	if (di->cookie == NULL) {
206500856ebSRafal Jaworowski 		/* start over - clean up enumeration */
207500856ebSRafal Jaworowski 		dev_enum_reset();	/* XXX shouldn't the name contain 'stor'? */
208500856ebSRafal Jaworowski 		debugf("RESTART ENUM\n");
209500856ebSRafal Jaworowski 
210500856ebSRafal Jaworowski 		/* net device enumeration first */
211500856ebSRafal Jaworowski 		if (dev_enum_net(di))
212500856ebSRafal Jaworowski 			return 0;
213500856ebSRafal Jaworowski 	}
214500856ebSRafal Jaworowski 
215500856ebSRafal Jaworowski 	/*
216500856ebSRafal Jaworowski 	 * The hidden assumption is there can only be one active network
217500856ebSRafal Jaworowski 	 * device and it is identified upon enumeration (re)start, so there's
218500856ebSRafal Jaworowski 	 * no point in trying to find network devices in other cases than the
219500856ebSRafal Jaworowski 	 * (re)start and hence the 'next' device can only be storage
220500856ebSRafal Jaworowski 	 */
221500856ebSRafal Jaworowski 	if (!dev_enum_storage(di))
222500856ebSRafal Jaworowski 		/* make sure we mark there are no more devices */
223500856ebSRafal Jaworowski 		di->cookie = NULL;
224500856ebSRafal Jaworowski 
225500856ebSRafal Jaworowski 	return 0;
226500856ebSRafal Jaworowski }
227500856ebSRafal Jaworowski 
228500856ebSRafal Jaworowski 
API_dev_open(va_list ap)229500856ebSRafal Jaworowski static int API_dev_open(va_list ap)
230500856ebSRafal Jaworowski {
231500856ebSRafal Jaworowski 	struct device_info *di;
232500856ebSRafal Jaworowski 	int err = 0;
233500856ebSRafal Jaworowski 
234500856ebSRafal Jaworowski 	/* arg is ptr to the device_info struct */
23578757d52SStanislav Galabov 	di = (struct device_info *)va_arg(ap, uintptr_t);
236500856ebSRafal Jaworowski 	if (di == NULL)
237500856ebSRafal Jaworowski 		return API_EINVAL;
238500856ebSRafal Jaworowski 
239500856ebSRafal Jaworowski 	/* Allow only one consumer of the device at a time */
240500856ebSRafal Jaworowski 	if (di->state == DEV_STA_OPEN)
241500856ebSRafal Jaworowski 		return API_EBUSY;
242500856ebSRafal Jaworowski 
243500856ebSRafal Jaworowski 	if (di->cookie == NULL)
244500856ebSRafal Jaworowski 		return API_ENODEV;
245500856ebSRafal Jaworowski 
246500856ebSRafal Jaworowski 	if (di->type & DEV_TYP_STOR)
247500856ebSRafal Jaworowski 		err = dev_open_stor(di->cookie);
248500856ebSRafal Jaworowski 
249500856ebSRafal Jaworowski 	else if (di->type & DEV_TYP_NET)
250500856ebSRafal Jaworowski 		err = dev_open_net(di->cookie);
251500856ebSRafal Jaworowski 	else
252500856ebSRafal Jaworowski 		err = API_ENODEV;
253500856ebSRafal Jaworowski 
254500856ebSRafal Jaworowski 	if (!err)
255500856ebSRafal Jaworowski 		di->state = DEV_STA_OPEN;
256500856ebSRafal Jaworowski 
257500856ebSRafal Jaworowski 	return err;
258500856ebSRafal Jaworowski }
259500856ebSRafal Jaworowski 
260500856ebSRafal Jaworowski 
API_dev_close(va_list ap)261500856ebSRafal Jaworowski static int API_dev_close(va_list ap)
262500856ebSRafal Jaworowski {
263500856ebSRafal Jaworowski 	struct device_info *di;
264500856ebSRafal Jaworowski 	int err = 0;
265500856ebSRafal Jaworowski 
266500856ebSRafal Jaworowski 	/* arg is ptr to the device_info struct */
26778757d52SStanislav Galabov 	di = (struct device_info *)va_arg(ap, uintptr_t);
268500856ebSRafal Jaworowski 	if (di == NULL)
269500856ebSRafal Jaworowski 		return API_EINVAL;
270500856ebSRafal Jaworowski 
271500856ebSRafal Jaworowski 	if (di->state == DEV_STA_CLOSED)
272500856ebSRafal Jaworowski 		return 0;
273500856ebSRafal Jaworowski 
274500856ebSRafal Jaworowski 	if (di->cookie == NULL)
275500856ebSRafal Jaworowski 		return API_ENODEV;
276500856ebSRafal Jaworowski 
277500856ebSRafal Jaworowski 	if (di->type & DEV_TYP_STOR)
278500856ebSRafal Jaworowski 		err = dev_close_stor(di->cookie);
279500856ebSRafal Jaworowski 
280500856ebSRafal Jaworowski 	else if (di->type & DEV_TYP_NET)
281500856ebSRafal Jaworowski 		err = dev_close_net(di->cookie);
282500856ebSRafal Jaworowski 	else
283500856ebSRafal Jaworowski 		/*
284500856ebSRafal Jaworowski 		 * In case of unknown device we cannot change its state, so
285500856ebSRafal Jaworowski 		 * only return error code
286500856ebSRafal Jaworowski 		 */
287500856ebSRafal Jaworowski 		err = API_ENODEV;
288500856ebSRafal Jaworowski 
289500856ebSRafal Jaworowski 	if (!err)
290500856ebSRafal Jaworowski 		di->state = DEV_STA_CLOSED;
291500856ebSRafal Jaworowski 
292500856ebSRafal Jaworowski 	return err;
293500856ebSRafal Jaworowski }
294500856ebSRafal Jaworowski 
295500856ebSRafal Jaworowski 
296500856ebSRafal Jaworowski /*
297500856ebSRafal Jaworowski  * Notice: this is for sending network packets only, as U-Boot does not
298500856ebSRafal Jaworowski  * support writing to storage at the moment (12.2007)
299500856ebSRafal Jaworowski  *
300500856ebSRafal Jaworowski  * pseudo signature:
301500856ebSRafal Jaworowski  *
302500856ebSRafal Jaworowski  * int API_dev_write(
303500856ebSRafal Jaworowski  *	struct device_info *di,
304500856ebSRafal Jaworowski  *	void *buf,
305500856ebSRafal Jaworowski  *	int *len
306500856ebSRafal Jaworowski  * )
307500856ebSRafal Jaworowski  *
308500856ebSRafal Jaworowski  * buf:	ptr to buffer from where to get the data to send
309500856ebSRafal Jaworowski  *
310500856ebSRafal Jaworowski  * len: length of packet to be sent (in bytes)
311500856ebSRafal Jaworowski  *
312500856ebSRafal Jaworowski  */
API_dev_write(va_list ap)313500856ebSRafal Jaworowski static int API_dev_write(va_list ap)
314500856ebSRafal Jaworowski {
315500856ebSRafal Jaworowski 	struct device_info *di;
316500856ebSRafal Jaworowski 	void *buf;
317500856ebSRafal Jaworowski 	int *len;
318500856ebSRafal Jaworowski 	int err = 0;
319500856ebSRafal Jaworowski 
320500856ebSRafal Jaworowski 	/* 1. arg is ptr to the device_info struct */
32178757d52SStanislav Galabov 	di = (struct device_info *)va_arg(ap, uintptr_t);
322500856ebSRafal Jaworowski 	if (di == NULL)
323500856ebSRafal Jaworowski 		return API_EINVAL;
324500856ebSRafal Jaworowski 
325500856ebSRafal Jaworowski 	/* XXX should we check if device is open? i.e. the ->state ? */
326500856ebSRafal Jaworowski 
327500856ebSRafal Jaworowski 	if (di->cookie == NULL)
328500856ebSRafal Jaworowski 		return API_ENODEV;
329500856ebSRafal Jaworowski 
330500856ebSRafal Jaworowski 	/* 2. arg is ptr to buffer from where to get data to write */
33178757d52SStanislav Galabov 	buf = (void *)va_arg(ap, uintptr_t);
332500856ebSRafal Jaworowski 	if (buf == NULL)
333500856ebSRafal Jaworowski 		return API_EINVAL;
334500856ebSRafal Jaworowski 
335500856ebSRafal Jaworowski 	/* 3. arg is length of buffer */
33678757d52SStanislav Galabov 	len = (int *)va_arg(ap, uintptr_t);
337500856ebSRafal Jaworowski 	if (len == NULL)
338500856ebSRafal Jaworowski 		return API_EINVAL;
339500856ebSRafal Jaworowski 	if (*len <= 0)
340500856ebSRafal Jaworowski 		return API_EINVAL;
341500856ebSRafal Jaworowski 
342500856ebSRafal Jaworowski 	if (di->type & DEV_TYP_STOR)
343500856ebSRafal Jaworowski 		/*
344500856ebSRafal Jaworowski 		 * write to storage is currently not supported by U-Boot:
345500856ebSRafal Jaworowski 		 * no storage device implements block_write() method
346500856ebSRafal Jaworowski 		 */
347500856ebSRafal Jaworowski 		return API_ENODEV;
348500856ebSRafal Jaworowski 
349500856ebSRafal Jaworowski 	else if (di->type & DEV_TYP_NET)
350500856ebSRafal Jaworowski 		err = dev_write_net(di->cookie, buf, *len);
351500856ebSRafal Jaworowski 	else
352500856ebSRafal Jaworowski 		err = API_ENODEV;
353500856ebSRafal Jaworowski 
354500856ebSRafal Jaworowski 	return err;
355500856ebSRafal Jaworowski }
356500856ebSRafal Jaworowski 
357500856ebSRafal Jaworowski 
358500856ebSRafal Jaworowski /*
359500856ebSRafal Jaworowski  * pseudo signature:
360500856ebSRafal Jaworowski  *
361500856ebSRafal Jaworowski  * int API_dev_read(
362500856ebSRafal Jaworowski  *	struct device_info *di,
363500856ebSRafal Jaworowski  *	void *buf,
364500856ebSRafal Jaworowski  *	size_t *len,
365500856ebSRafal Jaworowski  *	unsigned long *start
366500856ebSRafal Jaworowski  *	size_t *act_len
367500856ebSRafal Jaworowski  * )
368500856ebSRafal Jaworowski  *
369500856ebSRafal Jaworowski  * buf:	ptr to buffer where to put the read data
370500856ebSRafal Jaworowski  *
371500856ebSRafal Jaworowski  * len: ptr to length to be read
372500856ebSRafal Jaworowski  *      - network: len of packet to read (in bytes)
373500856ebSRafal Jaworowski  *      - storage: # of blocks to read (can vary in size depending on define)
374500856ebSRafal Jaworowski  *
375500856ebSRafal Jaworowski  * start: ptr to start block (only used for storage devices, ignored for
376500856ebSRafal Jaworowski  *        network)
377500856ebSRafal Jaworowski  *
378500856ebSRafal Jaworowski  * act_len: ptr to where to put the len actually read
379500856ebSRafal Jaworowski  */
API_dev_read(va_list ap)380500856ebSRafal Jaworowski static int API_dev_read(va_list ap)
381500856ebSRafal Jaworowski {
382500856ebSRafal Jaworowski 	struct device_info *di;
383500856ebSRafal Jaworowski 	void *buf;
384500856ebSRafal Jaworowski 	lbasize_t *len_stor, *act_len_stor;
385500856ebSRafal Jaworowski 	lbastart_t *start;
386500856ebSRafal Jaworowski 	int *len_net, *act_len_net;
387500856ebSRafal Jaworowski 
388500856ebSRafal Jaworowski 	/* 1. arg is ptr to the device_info struct */
38978757d52SStanislav Galabov 	di = (struct device_info *)va_arg(ap, uintptr_t);
390500856ebSRafal Jaworowski 	if (di == NULL)
391500856ebSRafal Jaworowski 		return API_EINVAL;
392500856ebSRafal Jaworowski 
393500856ebSRafal Jaworowski 	/* XXX should we check if device is open? i.e. the ->state ? */
394500856ebSRafal Jaworowski 
395500856ebSRafal Jaworowski 	if (di->cookie == NULL)
396500856ebSRafal Jaworowski 		return API_ENODEV;
397500856ebSRafal Jaworowski 
398500856ebSRafal Jaworowski 	/* 2. arg is ptr to buffer from where to put the read data */
39978757d52SStanislav Galabov 	buf = (void *)va_arg(ap, uintptr_t);
400500856ebSRafal Jaworowski 	if (buf == NULL)
401500856ebSRafal Jaworowski 		return API_EINVAL;
402500856ebSRafal Jaworowski 
403500856ebSRafal Jaworowski 	if (di->type & DEV_TYP_STOR) {
404500856ebSRafal Jaworowski 		/* 3. arg - ptr to var with # of blocks to read */
40578757d52SStanislav Galabov 		len_stor = (lbasize_t *)va_arg(ap, uintptr_t);
406500856ebSRafal Jaworowski 		if (!len_stor)
407500856ebSRafal Jaworowski 			return API_EINVAL;
408500856ebSRafal Jaworowski 		if (*len_stor <= 0)
409500856ebSRafal Jaworowski 			return API_EINVAL;
410500856ebSRafal Jaworowski 
411500856ebSRafal Jaworowski 		/* 4. arg - ptr to var with start block */
41278757d52SStanislav Galabov 		start = (lbastart_t *)va_arg(ap, uintptr_t);
413500856ebSRafal Jaworowski 
414500856ebSRafal Jaworowski 		/* 5. arg - ptr to var where to put the len actually read */
41578757d52SStanislav Galabov 		act_len_stor = (lbasize_t *)va_arg(ap, uintptr_t);
416500856ebSRafal Jaworowski 		if (!act_len_stor)
417500856ebSRafal Jaworowski 			return API_EINVAL;
418500856ebSRafal Jaworowski 
419500856ebSRafal Jaworowski 		*act_len_stor = dev_read_stor(di->cookie, buf, *len_stor, *start);
420500856ebSRafal Jaworowski 
421500856ebSRafal Jaworowski 	} else if (di->type & DEV_TYP_NET) {
422500856ebSRafal Jaworowski 
423500856ebSRafal Jaworowski 		/* 3. arg points to the var with length of packet to read */
42478757d52SStanislav Galabov 		len_net = (int *)va_arg(ap, uintptr_t);
425500856ebSRafal Jaworowski 		if (!len_net)
426500856ebSRafal Jaworowski 			return API_EINVAL;
427500856ebSRafal Jaworowski 		if (*len_net <= 0)
428500856ebSRafal Jaworowski 			return API_EINVAL;
429500856ebSRafal Jaworowski 
430500856ebSRafal Jaworowski 		/* 4. - ptr to var where to put the len actually read */
43178757d52SStanislav Galabov 		act_len_net = (int *)va_arg(ap, uintptr_t);
432500856ebSRafal Jaworowski 		if (!act_len_net)
433500856ebSRafal Jaworowski 			return API_EINVAL;
434500856ebSRafal Jaworowski 
435500856ebSRafal Jaworowski 		*act_len_net = dev_read_net(di->cookie, buf, *len_net);
436500856ebSRafal Jaworowski 
437500856ebSRafal Jaworowski 	} else
438500856ebSRafal Jaworowski 		return API_ENODEV;
439500856ebSRafal Jaworowski 
440500856ebSRafal Jaworowski 	return 0;
441500856ebSRafal Jaworowski }
442500856ebSRafal Jaworowski 
443500856ebSRafal Jaworowski 
444500856ebSRafal Jaworowski /*
445500856ebSRafal Jaworowski  * pseudo signature:
446500856ebSRafal Jaworowski  *
447500856ebSRafal Jaworowski  * int API_env_get(const char *name, char **value)
448500856ebSRafal Jaworowski  *
449500856ebSRafal Jaworowski  * name: ptr to name of env var
450500856ebSRafal Jaworowski  */
API_env_get(va_list ap)451500856ebSRafal Jaworowski static int API_env_get(va_list ap)
452500856ebSRafal Jaworowski {
453500856ebSRafal Jaworowski 	char *name, **value;
454500856ebSRafal Jaworowski 
45578757d52SStanislav Galabov 	if ((name = (char *)va_arg(ap, uintptr_t)) == NULL)
456500856ebSRafal Jaworowski 		return API_EINVAL;
45778757d52SStanislav Galabov 	if ((value = (char **)va_arg(ap, uintptr_t)) == NULL)
458500856ebSRafal Jaworowski 		return API_EINVAL;
459500856ebSRafal Jaworowski 
46000caae6dSSimon Glass 	*value = env_get(name);
461500856ebSRafal Jaworowski 
462500856ebSRafal Jaworowski 	return 0;
463500856ebSRafal Jaworowski }
464500856ebSRafal Jaworowski 
465500856ebSRafal Jaworowski /*
466500856ebSRafal Jaworowski  * pseudo signature:
467500856ebSRafal Jaworowski  *
468500856ebSRafal Jaworowski  * int API_env_set(const char *name, const char *value)
469500856ebSRafal Jaworowski  *
470500856ebSRafal Jaworowski  * name: ptr to name of env var
471500856ebSRafal Jaworowski  *
472500856ebSRafal Jaworowski  * value: ptr to value to be set
473500856ebSRafal Jaworowski  */
API_env_set(va_list ap)474500856ebSRafal Jaworowski static int API_env_set(va_list ap)
475500856ebSRafal Jaworowski {
476500856ebSRafal Jaworowski 	char *name, *value;
477500856ebSRafal Jaworowski 
47878757d52SStanislav Galabov 	if ((name = (char *)va_arg(ap, uintptr_t)) == NULL)
479500856ebSRafal Jaworowski 		return API_EINVAL;
48078757d52SStanislav Galabov 	if ((value = (char *)va_arg(ap, uintptr_t)) == NULL)
481500856ebSRafal Jaworowski 		return API_EINVAL;
482500856ebSRafal Jaworowski 
483382bee57SSimon Glass 	env_set(name, value);
484500856ebSRafal Jaworowski 
485500856ebSRafal Jaworowski 	return 0;
486500856ebSRafal Jaworowski }
487500856ebSRafal Jaworowski 
488500856ebSRafal Jaworowski /*
489500856ebSRafal Jaworowski  * pseudo signature:
490500856ebSRafal Jaworowski  *
491500856ebSRafal Jaworowski  * int API_env_enum(const char *last, char **next)
492500856ebSRafal Jaworowski  *
493500856ebSRafal Jaworowski  * last: ptr to name of env var found in last iteration
494500856ebSRafal Jaworowski  */
API_env_enum(va_list ap)495500856ebSRafal Jaworowski static int API_env_enum(va_list ap)
496500856ebSRafal Jaworowski {
4976215bd4cSEmmanuel Vadot 	int i, buflen;
4986215bd4cSEmmanuel Vadot 	char *last, **next, *s;
4996215bd4cSEmmanuel Vadot 	ENTRY *match, search;
5006215bd4cSEmmanuel Vadot 	static char *var;
501500856ebSRafal Jaworowski 
50278757d52SStanislav Galabov 	last = (char *)va_arg(ap, unsigned long);
503500856ebSRafal Jaworowski 
50478757d52SStanislav Galabov 	if ((next = (char **)va_arg(ap, uintptr_t)) == NULL)
505500856ebSRafal Jaworowski 		return API_EINVAL;
506500856ebSRafal Jaworowski 
5076215bd4cSEmmanuel Vadot 	if (last == NULL) {
5086215bd4cSEmmanuel Vadot 		var = NULL;
5096215bd4cSEmmanuel Vadot 		i = 0;
5106215bd4cSEmmanuel Vadot 	} else {
5116215bd4cSEmmanuel Vadot 		var = strdup(last);
5126215bd4cSEmmanuel Vadot 		s = strchr(var, '=');
5136215bd4cSEmmanuel Vadot 		if (s != NULL)
5146215bd4cSEmmanuel Vadot 			*s = 0;
5156215bd4cSEmmanuel Vadot 		search.key = var;
5166215bd4cSEmmanuel Vadot 		i = hsearch_r(search, FIND, &match, &env_htab, 0);
5176215bd4cSEmmanuel Vadot 		if (i == 0) {
5186215bd4cSEmmanuel Vadot 			i = API_EINVAL;
5196215bd4cSEmmanuel Vadot 			goto done;
5206215bd4cSEmmanuel Vadot 		}
5216215bd4cSEmmanuel Vadot 	}
522500856ebSRafal Jaworowski 
5236215bd4cSEmmanuel Vadot 	/* match the next entry after i */
5246215bd4cSEmmanuel Vadot 	i = hmatch_r("", i, &match, &env_htab);
5256215bd4cSEmmanuel Vadot 	if (i == 0)
5266215bd4cSEmmanuel Vadot 		goto done;
5276215bd4cSEmmanuel Vadot 	buflen = strlen(match->key) + strlen(match->data) + 2;
5286215bd4cSEmmanuel Vadot 	var = realloc(var, buflen);
5296215bd4cSEmmanuel Vadot 	snprintf(var, buflen, "%s=%s", match->key, match->data);
5306215bd4cSEmmanuel Vadot 	*next = var;
531500856ebSRafal Jaworowski 	return 0;
532500856ebSRafal Jaworowski 
5336215bd4cSEmmanuel Vadot done:
5346215bd4cSEmmanuel Vadot 	free(var);
5356215bd4cSEmmanuel Vadot 	var = NULL;
536500856ebSRafal Jaworowski 	*next = NULL;
5376215bd4cSEmmanuel Vadot 	return i;
538500856ebSRafal Jaworowski }
539500856ebSRafal Jaworowski 
540a2a5729fSChe-Liang Chiou /*
541a2a5729fSChe-Liang Chiou  * pseudo signature:
542a2a5729fSChe-Liang Chiou  *
543a2a5729fSChe-Liang Chiou  * int API_display_get_info(int type, struct display_info *di)
544a2a5729fSChe-Liang Chiou  */
API_display_get_info(va_list ap)545a2a5729fSChe-Liang Chiou static int API_display_get_info(va_list ap)
546a2a5729fSChe-Liang Chiou {
547a2a5729fSChe-Liang Chiou 	int type;
548a2a5729fSChe-Liang Chiou 	struct display_info *di;
549a2a5729fSChe-Liang Chiou 
550a2a5729fSChe-Liang Chiou 	type = va_arg(ap, int);
551a2a5729fSChe-Liang Chiou 	di = va_arg(ap, struct display_info *);
552a2a5729fSChe-Liang Chiou 
553a2a5729fSChe-Liang Chiou 	return display_get_info(type, di);
554a2a5729fSChe-Liang Chiou }
555a2a5729fSChe-Liang Chiou 
556a2a5729fSChe-Liang Chiou /*
557a2a5729fSChe-Liang Chiou  * pseudo signature:
558a2a5729fSChe-Liang Chiou  *
559a2a5729fSChe-Liang Chiou  * int API_display_draw_bitmap(ulong bitmap, int x, int y)
560a2a5729fSChe-Liang Chiou  */
API_display_draw_bitmap(va_list ap)561a2a5729fSChe-Liang Chiou static int API_display_draw_bitmap(va_list ap)
562a2a5729fSChe-Liang Chiou {
563a2a5729fSChe-Liang Chiou 	ulong bitmap;
564a2a5729fSChe-Liang Chiou 	int x, y;
565a2a5729fSChe-Liang Chiou 
566a2a5729fSChe-Liang Chiou 	bitmap = va_arg(ap, ulong);
567a2a5729fSChe-Liang Chiou 	x = va_arg(ap, int);
568a2a5729fSChe-Liang Chiou 	y = va_arg(ap, int);
569a2a5729fSChe-Liang Chiou 
570a2a5729fSChe-Liang Chiou 	return display_draw_bitmap(bitmap, x, y);
571a2a5729fSChe-Liang Chiou }
572a2a5729fSChe-Liang Chiou 
573a2a5729fSChe-Liang Chiou /*
574a2a5729fSChe-Liang Chiou  * pseudo signature:
575a2a5729fSChe-Liang Chiou  *
576a2a5729fSChe-Liang Chiou  * void API_display_clear(void)
577a2a5729fSChe-Liang Chiou  */
API_display_clear(va_list ap)578a2a5729fSChe-Liang Chiou static int API_display_clear(va_list ap)
579a2a5729fSChe-Liang Chiou {
580a2a5729fSChe-Liang Chiou 	display_clear();
581a2a5729fSChe-Liang Chiou 	return 0;
582a2a5729fSChe-Liang Chiou }
583a2a5729fSChe-Liang Chiou 
584500856ebSRafal Jaworowski static cfp_t calls_table[API_MAXCALL] = { NULL, };
585500856ebSRafal Jaworowski 
586500856ebSRafal Jaworowski /*
587500856ebSRafal Jaworowski  * The main syscall entry point - this is not reentrant, only one call is
588500856ebSRafal Jaworowski  * serviced until finished.
589500856ebSRafal Jaworowski  *
590500856ebSRafal Jaworowski  * e.g. syscall(1, int *, u_int32_t, u_int32_t, u_int32_t, u_int32_t);
591500856ebSRafal Jaworowski  *
592500856ebSRafal Jaworowski  * call:	syscall number
593500856ebSRafal Jaworowski  *
594500856ebSRafal Jaworowski  * retval:	points to the return value placeholder, this is the place the
595500856ebSRafal Jaworowski  *		syscall puts its return value, if NULL the caller does not
596500856ebSRafal Jaworowski  *		expect a return value
597500856ebSRafal Jaworowski  *
598500856ebSRafal Jaworowski  * ...		syscall arguments (variable number)
599500856ebSRafal Jaworowski  *
600500856ebSRafal Jaworowski  * returns:	0 if the call not found, 1 if serviced
601500856ebSRafal Jaworowski  */
syscall(int call,int * retval,...)602500856ebSRafal Jaworowski int syscall(int call, int *retval, ...)
603500856ebSRafal Jaworowski {
604500856ebSRafal Jaworowski 	va_list	ap;
605500856ebSRafal Jaworowski 	int rv;
606500856ebSRafal Jaworowski 
60720e5ed13SJean-Christophe PLAGNIOL-VILLARD 	if (call < 0 || call >= calls_no) {
608500856ebSRafal Jaworowski 		debugf("invalid call #%d\n", call);
609500856ebSRafal Jaworowski 		return 0;
610500856ebSRafal Jaworowski 	}
611500856ebSRafal Jaworowski 
612500856ebSRafal Jaworowski 	if (calls_table[call] == NULL) {
613500856ebSRafal Jaworowski 		debugf("syscall #%d does not have a handler\n", call);
614500856ebSRafal Jaworowski 		return 0;
615500856ebSRafal Jaworowski 	}
616500856ebSRafal Jaworowski 
617500856ebSRafal Jaworowski 	va_start(ap, retval);
618500856ebSRafal Jaworowski 	rv = calls_table[call](ap);
619500856ebSRafal Jaworowski 	if (retval != NULL)
620500856ebSRafal Jaworowski 		*retval = rv;
621500856ebSRafal Jaworowski 
622500856ebSRafal Jaworowski 	return 1;
623500856ebSRafal Jaworowski }
624500856ebSRafal Jaworowski 
api_init(void)625500856ebSRafal Jaworowski void api_init(void)
626500856ebSRafal Jaworowski {
6275cc9e6b7Sxypron.glpk@gmx.de 	struct api_signature *sig;
628500856ebSRafal Jaworowski 
629500856ebSRafal Jaworowski 	/* TODO put this into linker set one day... */
630500856ebSRafal Jaworowski 	calls_table[API_RSVD] = NULL;
631500856ebSRafal Jaworowski 	calls_table[API_GETC] = &API_getc;
632500856ebSRafal Jaworowski 	calls_table[API_PUTC] = &API_putc;
633500856ebSRafal Jaworowski 	calls_table[API_TSTC] = &API_tstc;
634500856ebSRafal Jaworowski 	calls_table[API_PUTS] = &API_puts;
635500856ebSRafal Jaworowski 	calls_table[API_RESET] = &API_reset;
636500856ebSRafal Jaworowski 	calls_table[API_GET_SYS_INFO] = &API_get_sys_info;
637500856ebSRafal Jaworowski 	calls_table[API_UDELAY] = &API_udelay;
638500856ebSRafal Jaworowski 	calls_table[API_GET_TIMER] = &API_get_timer;
639500856ebSRafal Jaworowski 	calls_table[API_DEV_ENUM] = &API_dev_enum;
640500856ebSRafal Jaworowski 	calls_table[API_DEV_OPEN] = &API_dev_open;
641500856ebSRafal Jaworowski 	calls_table[API_DEV_CLOSE] = &API_dev_close;
642500856ebSRafal Jaworowski 	calls_table[API_DEV_READ] = &API_dev_read;
643500856ebSRafal Jaworowski 	calls_table[API_DEV_WRITE] = &API_dev_write;
644500856ebSRafal Jaworowski 	calls_table[API_ENV_GET] = &API_env_get;
645500856ebSRafal Jaworowski 	calls_table[API_ENV_SET] = &API_env_set;
646500856ebSRafal Jaworowski 	calls_table[API_ENV_ENUM] = &API_env_enum;
647a2a5729fSChe-Liang Chiou 	calls_table[API_DISPLAY_GET_INFO] = &API_display_get_info;
648a2a5729fSChe-Liang Chiou 	calls_table[API_DISPLAY_DRAW_BITMAP] = &API_display_draw_bitmap;
649a2a5729fSChe-Liang Chiou 	calls_table[API_DISPLAY_CLEAR] = &API_display_clear;
650500856ebSRafal Jaworowski 	calls_no = API_MAXCALL;
651500856ebSRafal Jaworowski 
652500856ebSRafal Jaworowski 	debugf("API initialized with %d calls\n", calls_no);
653500856ebSRafal Jaworowski 
654500856ebSRafal Jaworowski 	dev_stor_init();
655500856ebSRafal Jaworowski 
656500856ebSRafal Jaworowski 	/*
657500856ebSRafal Jaworowski 	 * Produce the signature so the API consumers can find it
658500856ebSRafal Jaworowski 	 */
659500856ebSRafal Jaworowski 	sig = malloc(sizeof(struct api_signature));
660500856ebSRafal Jaworowski 	if (sig == NULL) {
661500856ebSRafal Jaworowski 		printf("API: could not allocate memory for the signature!\n");
662500856ebSRafal Jaworowski 		return;
663500856ebSRafal Jaworowski 	}
664500856ebSRafal Jaworowski 
665018f5303SSimon Glass 	env_set_hex("api_address", (unsigned long)sig);
66678757d52SStanislav Galabov 	debugf("API sig @ 0x%lX\n", (unsigned long)sig);
667500856ebSRafal Jaworowski 	memcpy(sig->magic, API_SIG_MAGIC, 8);
668500856ebSRafal Jaworowski 	sig->version = API_SIG_VERSION;
669500856ebSRafal Jaworowski 	sig->syscall = &syscall;
670500856ebSRafal Jaworowski 	sig->checksum = 0;
671500856ebSRafal Jaworowski 	sig->checksum = crc32(0, (unsigned char *)sig,
672500856ebSRafal Jaworowski 			      sizeof(struct api_signature));
67378757d52SStanislav Galabov 	debugf("syscall entry: 0x%lX\n", (unsigned long)sig->syscall);
674500856ebSRafal Jaworowski }
675500856ebSRafal Jaworowski 
platform_set_mr(struct sys_info * si,unsigned long start,unsigned long size,int flags)676500856ebSRafal Jaworowski void platform_set_mr(struct sys_info *si, unsigned long start, unsigned long size,
677500856ebSRafal Jaworowski 			int flags)
678500856ebSRafal Jaworowski {
679500856ebSRafal Jaworowski 	int i;
680500856ebSRafal Jaworowski 
681500856ebSRafal Jaworowski 	if (!si->mr || !size || (flags == 0))
682500856ebSRafal Jaworowski 		return;
683500856ebSRafal Jaworowski 
684500856ebSRafal Jaworowski 	/* find free slot */
685500856ebSRafal Jaworowski 	for (i = 0; i < si->mr_no; i++)
686500856ebSRafal Jaworowski 		if (si->mr[i].flags == 0) {
687500856ebSRafal Jaworowski 			/* insert new mem region */
688500856ebSRafal Jaworowski 			si->mr[i].start = start;
689500856ebSRafal Jaworowski 			si->mr[i].size = size;
690500856ebSRafal Jaworowski 			si->mr[i].flags = flags;
691500856ebSRafal Jaworowski 			return;
692500856ebSRafal Jaworowski 		}
693500856ebSRafal Jaworowski }
694