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