1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * (C) Copyright 2007 Semihalf
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Written by: Rafal Jaworowski <raj@semihalf.com>
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * SPDX-License-Identifier: GPL-2.0+
7*4882a593Smuzhiyun */
8*4882a593Smuzhiyun
9*4882a593Smuzhiyun #include <config.h>
10*4882a593Smuzhiyun #include <command.h>
11*4882a593Smuzhiyun #include <common.h>
12*4882a593Smuzhiyun #include <malloc.h>
13*4882a593Smuzhiyun #include <environment.h>
14*4882a593Smuzhiyun #include <linux/types.h>
15*4882a593Smuzhiyun #include <api_public.h>
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun #include "api_private.h"
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun #define DEBUG
20*4882a593Smuzhiyun #undef DEBUG
21*4882a593Smuzhiyun
22*4882a593Smuzhiyun /*****************************************************************************
23*4882a593Smuzhiyun *
24*4882a593Smuzhiyun * This is the API core.
25*4882a593Smuzhiyun *
26*4882a593Smuzhiyun * API_ functions are part of U-Boot code and constitute the lowest level
27*4882a593Smuzhiyun * calls:
28*4882a593Smuzhiyun *
29*4882a593Smuzhiyun * - they know what values they need as arguments
30*4882a593Smuzhiyun * - their direct return value pertains to the API_ "shell" itself (0 on
31*4882a593Smuzhiyun * success, some error code otherwise)
32*4882a593Smuzhiyun * - if the call returns a value it is buried within arguments
33*4882a593Smuzhiyun *
34*4882a593Smuzhiyun ****************************************************************************/
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun #ifdef DEBUG
37*4882a593Smuzhiyun #define debugf(fmt, args...) do { printf("%s(): ", __func__); printf(fmt, ##args); } while (0)
38*4882a593Smuzhiyun #else
39*4882a593Smuzhiyun #define debugf(fmt, args...)
40*4882a593Smuzhiyun #endif
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun typedef int (*cfp_t)(va_list argp);
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun static int calls_no;
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun /*
47*4882a593Smuzhiyun * pseudo signature:
48*4882a593Smuzhiyun *
49*4882a593Smuzhiyun * int API_getc(int *c)
50*4882a593Smuzhiyun */
API_getc(va_list ap)51*4882a593Smuzhiyun static int API_getc(va_list ap)
52*4882a593Smuzhiyun {
53*4882a593Smuzhiyun int *c;
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun if ((c = (int *)va_arg(ap, uintptr_t)) == NULL)
56*4882a593Smuzhiyun return API_EINVAL;
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun *c = getc();
59*4882a593Smuzhiyun return 0;
60*4882a593Smuzhiyun }
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun /*
63*4882a593Smuzhiyun * pseudo signature:
64*4882a593Smuzhiyun *
65*4882a593Smuzhiyun * int API_tstc(int *c)
66*4882a593Smuzhiyun */
API_tstc(va_list ap)67*4882a593Smuzhiyun static int API_tstc(va_list ap)
68*4882a593Smuzhiyun {
69*4882a593Smuzhiyun int *t;
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun if ((t = (int *)va_arg(ap, uintptr_t)) == NULL)
72*4882a593Smuzhiyun return API_EINVAL;
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun *t = tstc();
75*4882a593Smuzhiyun return 0;
76*4882a593Smuzhiyun }
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun /*
79*4882a593Smuzhiyun * pseudo signature:
80*4882a593Smuzhiyun *
81*4882a593Smuzhiyun * int API_putc(char *ch)
82*4882a593Smuzhiyun */
API_putc(va_list ap)83*4882a593Smuzhiyun static int API_putc(va_list ap)
84*4882a593Smuzhiyun {
85*4882a593Smuzhiyun char *c;
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun if ((c = (char *)va_arg(ap, uintptr_t)) == NULL)
88*4882a593Smuzhiyun return API_EINVAL;
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun putc(*c);
91*4882a593Smuzhiyun return 0;
92*4882a593Smuzhiyun }
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun /*
95*4882a593Smuzhiyun * pseudo signature:
96*4882a593Smuzhiyun *
97*4882a593Smuzhiyun * int API_puts(char **s)
98*4882a593Smuzhiyun */
API_puts(va_list ap)99*4882a593Smuzhiyun static int API_puts(va_list ap)
100*4882a593Smuzhiyun {
101*4882a593Smuzhiyun char *s;
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun if ((s = (char *)va_arg(ap, uintptr_t)) == NULL)
104*4882a593Smuzhiyun return API_EINVAL;
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun puts(s);
107*4882a593Smuzhiyun return 0;
108*4882a593Smuzhiyun }
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun /*
111*4882a593Smuzhiyun * pseudo signature:
112*4882a593Smuzhiyun *
113*4882a593Smuzhiyun * int API_reset(void)
114*4882a593Smuzhiyun */
API_reset(va_list ap)115*4882a593Smuzhiyun static int API_reset(va_list ap)
116*4882a593Smuzhiyun {
117*4882a593Smuzhiyun do_reset(NULL, 0, 0, NULL);
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun /* NOT REACHED */
120*4882a593Smuzhiyun return 0;
121*4882a593Smuzhiyun }
122*4882a593Smuzhiyun
123*4882a593Smuzhiyun /*
124*4882a593Smuzhiyun * pseudo signature:
125*4882a593Smuzhiyun *
126*4882a593Smuzhiyun * int API_get_sys_info(struct sys_info *si)
127*4882a593Smuzhiyun *
128*4882a593Smuzhiyun * fill out the sys_info struct containing selected parameters about the
129*4882a593Smuzhiyun * machine
130*4882a593Smuzhiyun */
API_get_sys_info(va_list ap)131*4882a593Smuzhiyun static int API_get_sys_info(va_list ap)
132*4882a593Smuzhiyun {
133*4882a593Smuzhiyun struct sys_info *si;
134*4882a593Smuzhiyun
135*4882a593Smuzhiyun si = (struct sys_info *)va_arg(ap, uintptr_t);
136*4882a593Smuzhiyun if (si == NULL)
137*4882a593Smuzhiyun return API_ENOMEM;
138*4882a593Smuzhiyun
139*4882a593Smuzhiyun return (platform_sys_info(si)) ? 0 : API_ENODEV;
140*4882a593Smuzhiyun }
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun /*
143*4882a593Smuzhiyun * pseudo signature:
144*4882a593Smuzhiyun *
145*4882a593Smuzhiyun * int API_udelay(unsigned long *udelay)
146*4882a593Smuzhiyun */
API_udelay(va_list ap)147*4882a593Smuzhiyun static int API_udelay(va_list ap)
148*4882a593Smuzhiyun {
149*4882a593Smuzhiyun unsigned long *d;
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun if ((d = (unsigned long *)va_arg(ap, unsigned long)) == NULL)
152*4882a593Smuzhiyun return API_EINVAL;
153*4882a593Smuzhiyun
154*4882a593Smuzhiyun udelay(*d);
155*4882a593Smuzhiyun return 0;
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun /*
159*4882a593Smuzhiyun * pseudo signature:
160*4882a593Smuzhiyun *
161*4882a593Smuzhiyun * int API_get_timer(unsigned long *current, unsigned long *base)
162*4882a593Smuzhiyun */
API_get_timer(va_list ap)163*4882a593Smuzhiyun static int API_get_timer(va_list ap)
164*4882a593Smuzhiyun {
165*4882a593Smuzhiyun unsigned long *base, *cur;
166*4882a593Smuzhiyun
167*4882a593Smuzhiyun cur = (unsigned long *)va_arg(ap, unsigned long);
168*4882a593Smuzhiyun if (cur == NULL)
169*4882a593Smuzhiyun return API_EINVAL;
170*4882a593Smuzhiyun
171*4882a593Smuzhiyun base = (unsigned long *)va_arg(ap, unsigned long);
172*4882a593Smuzhiyun if (base == NULL)
173*4882a593Smuzhiyun return API_EINVAL;
174*4882a593Smuzhiyun
175*4882a593Smuzhiyun *cur = get_timer(*base);
176*4882a593Smuzhiyun return 0;
177*4882a593Smuzhiyun }
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun
180*4882a593Smuzhiyun /*****************************************************************************
181*4882a593Smuzhiyun *
182*4882a593Smuzhiyun * pseudo signature:
183*4882a593Smuzhiyun *
184*4882a593Smuzhiyun * int API_dev_enum(struct device_info *)
185*4882a593Smuzhiyun *
186*4882a593Smuzhiyun *
187*4882a593Smuzhiyun * cookies uniqely identify the previously enumerated device instance and
188*4882a593Smuzhiyun * provide a hint for what to inspect in current enum iteration:
189*4882a593Smuzhiyun *
190*4882a593Smuzhiyun * - net: ð_device struct address from list pointed to by eth_devices
191*4882a593Smuzhiyun *
192*4882a593Smuzhiyun * - storage: struct blk_desc struct address from &ide_dev_desc[n],
193*4882a593Smuzhiyun * &scsi_dev_desc[n] and similar tables
194*4882a593Smuzhiyun *
195*4882a593Smuzhiyun ****************************************************************************/
196*4882a593Smuzhiyun
API_dev_enum(va_list ap)197*4882a593Smuzhiyun static int API_dev_enum(va_list ap)
198*4882a593Smuzhiyun {
199*4882a593Smuzhiyun struct device_info *di;
200*4882a593Smuzhiyun
201*4882a593Smuzhiyun /* arg is ptr to the device_info struct we are going to fill out */
202*4882a593Smuzhiyun di = (struct device_info *)va_arg(ap, uintptr_t);
203*4882a593Smuzhiyun if (di == NULL)
204*4882a593Smuzhiyun return API_EINVAL;
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun if (di->cookie == NULL) {
207*4882a593Smuzhiyun /* start over - clean up enumeration */
208*4882a593Smuzhiyun dev_enum_reset(); /* XXX shouldn't the name contain 'stor'? */
209*4882a593Smuzhiyun debugf("RESTART ENUM\n");
210*4882a593Smuzhiyun
211*4882a593Smuzhiyun /* net device enumeration first */
212*4882a593Smuzhiyun if (dev_enum_net(di))
213*4882a593Smuzhiyun return 0;
214*4882a593Smuzhiyun }
215*4882a593Smuzhiyun
216*4882a593Smuzhiyun /*
217*4882a593Smuzhiyun * The hidden assumption is there can only be one active network
218*4882a593Smuzhiyun * device and it is identified upon enumeration (re)start, so there's
219*4882a593Smuzhiyun * no point in trying to find network devices in other cases than the
220*4882a593Smuzhiyun * (re)start and hence the 'next' device can only be storage
221*4882a593Smuzhiyun */
222*4882a593Smuzhiyun if (!dev_enum_storage(di))
223*4882a593Smuzhiyun /* make sure we mark there are no more devices */
224*4882a593Smuzhiyun di->cookie = NULL;
225*4882a593Smuzhiyun
226*4882a593Smuzhiyun return 0;
227*4882a593Smuzhiyun }
228*4882a593Smuzhiyun
229*4882a593Smuzhiyun
API_dev_open(va_list ap)230*4882a593Smuzhiyun static int API_dev_open(va_list ap)
231*4882a593Smuzhiyun {
232*4882a593Smuzhiyun struct device_info *di;
233*4882a593Smuzhiyun int err = 0;
234*4882a593Smuzhiyun
235*4882a593Smuzhiyun /* arg is ptr to the device_info struct */
236*4882a593Smuzhiyun di = (struct device_info *)va_arg(ap, uintptr_t);
237*4882a593Smuzhiyun if (di == NULL)
238*4882a593Smuzhiyun return API_EINVAL;
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun /* Allow only one consumer of the device at a time */
241*4882a593Smuzhiyun if (di->state == DEV_STA_OPEN)
242*4882a593Smuzhiyun return API_EBUSY;
243*4882a593Smuzhiyun
244*4882a593Smuzhiyun if (di->cookie == NULL)
245*4882a593Smuzhiyun return API_ENODEV;
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun if (di->type & DEV_TYP_STOR)
248*4882a593Smuzhiyun err = dev_open_stor(di->cookie);
249*4882a593Smuzhiyun
250*4882a593Smuzhiyun else if (di->type & DEV_TYP_NET)
251*4882a593Smuzhiyun err = dev_open_net(di->cookie);
252*4882a593Smuzhiyun else
253*4882a593Smuzhiyun err = API_ENODEV;
254*4882a593Smuzhiyun
255*4882a593Smuzhiyun if (!err)
256*4882a593Smuzhiyun di->state = DEV_STA_OPEN;
257*4882a593Smuzhiyun
258*4882a593Smuzhiyun return err;
259*4882a593Smuzhiyun }
260*4882a593Smuzhiyun
261*4882a593Smuzhiyun
API_dev_close(va_list ap)262*4882a593Smuzhiyun static int API_dev_close(va_list ap)
263*4882a593Smuzhiyun {
264*4882a593Smuzhiyun struct device_info *di;
265*4882a593Smuzhiyun int err = 0;
266*4882a593Smuzhiyun
267*4882a593Smuzhiyun /* arg is ptr to the device_info struct */
268*4882a593Smuzhiyun di = (struct device_info *)va_arg(ap, uintptr_t);
269*4882a593Smuzhiyun if (di == NULL)
270*4882a593Smuzhiyun return API_EINVAL;
271*4882a593Smuzhiyun
272*4882a593Smuzhiyun if (di->state == DEV_STA_CLOSED)
273*4882a593Smuzhiyun return 0;
274*4882a593Smuzhiyun
275*4882a593Smuzhiyun if (di->cookie == NULL)
276*4882a593Smuzhiyun return API_ENODEV;
277*4882a593Smuzhiyun
278*4882a593Smuzhiyun if (di->type & DEV_TYP_STOR)
279*4882a593Smuzhiyun err = dev_close_stor(di->cookie);
280*4882a593Smuzhiyun
281*4882a593Smuzhiyun else if (di->type & DEV_TYP_NET)
282*4882a593Smuzhiyun err = dev_close_net(di->cookie);
283*4882a593Smuzhiyun else
284*4882a593Smuzhiyun /*
285*4882a593Smuzhiyun * In case of unknown device we cannot change its state, so
286*4882a593Smuzhiyun * only return error code
287*4882a593Smuzhiyun */
288*4882a593Smuzhiyun err = API_ENODEV;
289*4882a593Smuzhiyun
290*4882a593Smuzhiyun if (!err)
291*4882a593Smuzhiyun di->state = DEV_STA_CLOSED;
292*4882a593Smuzhiyun
293*4882a593Smuzhiyun return err;
294*4882a593Smuzhiyun }
295*4882a593Smuzhiyun
296*4882a593Smuzhiyun
297*4882a593Smuzhiyun /*
298*4882a593Smuzhiyun * Notice: this is for sending network packets only, as U-Boot does not
299*4882a593Smuzhiyun * support writing to storage at the moment (12.2007)
300*4882a593Smuzhiyun *
301*4882a593Smuzhiyun * pseudo signature:
302*4882a593Smuzhiyun *
303*4882a593Smuzhiyun * int API_dev_write(
304*4882a593Smuzhiyun * struct device_info *di,
305*4882a593Smuzhiyun * void *buf,
306*4882a593Smuzhiyun * int *len
307*4882a593Smuzhiyun * )
308*4882a593Smuzhiyun *
309*4882a593Smuzhiyun * buf: ptr to buffer from where to get the data to send
310*4882a593Smuzhiyun *
311*4882a593Smuzhiyun * len: length of packet to be sent (in bytes)
312*4882a593Smuzhiyun *
313*4882a593Smuzhiyun */
API_dev_write(va_list ap)314*4882a593Smuzhiyun static int API_dev_write(va_list ap)
315*4882a593Smuzhiyun {
316*4882a593Smuzhiyun struct device_info *di;
317*4882a593Smuzhiyun void *buf;
318*4882a593Smuzhiyun int *len;
319*4882a593Smuzhiyun int err = 0;
320*4882a593Smuzhiyun
321*4882a593Smuzhiyun /* 1. arg is ptr to the device_info struct */
322*4882a593Smuzhiyun di = (struct device_info *)va_arg(ap, uintptr_t);
323*4882a593Smuzhiyun if (di == NULL)
324*4882a593Smuzhiyun return API_EINVAL;
325*4882a593Smuzhiyun
326*4882a593Smuzhiyun /* XXX should we check if device is open? i.e. the ->state ? */
327*4882a593Smuzhiyun
328*4882a593Smuzhiyun if (di->cookie == NULL)
329*4882a593Smuzhiyun return API_ENODEV;
330*4882a593Smuzhiyun
331*4882a593Smuzhiyun /* 2. arg is ptr to buffer from where to get data to write */
332*4882a593Smuzhiyun buf = (void *)va_arg(ap, uintptr_t);
333*4882a593Smuzhiyun if (buf == NULL)
334*4882a593Smuzhiyun return API_EINVAL;
335*4882a593Smuzhiyun
336*4882a593Smuzhiyun /* 3. arg is length of buffer */
337*4882a593Smuzhiyun len = (int *)va_arg(ap, uintptr_t);
338*4882a593Smuzhiyun if (len == NULL)
339*4882a593Smuzhiyun return API_EINVAL;
340*4882a593Smuzhiyun if (*len <= 0)
341*4882a593Smuzhiyun return API_EINVAL;
342*4882a593Smuzhiyun
343*4882a593Smuzhiyun if (di->type & DEV_TYP_STOR)
344*4882a593Smuzhiyun /*
345*4882a593Smuzhiyun * write to storage is currently not supported by U-Boot:
346*4882a593Smuzhiyun * no storage device implements block_write() method
347*4882a593Smuzhiyun */
348*4882a593Smuzhiyun return API_ENODEV;
349*4882a593Smuzhiyun
350*4882a593Smuzhiyun else if (di->type & DEV_TYP_NET)
351*4882a593Smuzhiyun err = dev_write_net(di->cookie, buf, *len);
352*4882a593Smuzhiyun else
353*4882a593Smuzhiyun err = API_ENODEV;
354*4882a593Smuzhiyun
355*4882a593Smuzhiyun return err;
356*4882a593Smuzhiyun }
357*4882a593Smuzhiyun
358*4882a593Smuzhiyun
359*4882a593Smuzhiyun /*
360*4882a593Smuzhiyun * pseudo signature:
361*4882a593Smuzhiyun *
362*4882a593Smuzhiyun * int API_dev_read(
363*4882a593Smuzhiyun * struct device_info *di,
364*4882a593Smuzhiyun * void *buf,
365*4882a593Smuzhiyun * size_t *len,
366*4882a593Smuzhiyun * unsigned long *start
367*4882a593Smuzhiyun * size_t *act_len
368*4882a593Smuzhiyun * )
369*4882a593Smuzhiyun *
370*4882a593Smuzhiyun * buf: ptr to buffer where to put the read data
371*4882a593Smuzhiyun *
372*4882a593Smuzhiyun * len: ptr to length to be read
373*4882a593Smuzhiyun * - network: len of packet to read (in bytes)
374*4882a593Smuzhiyun * - storage: # of blocks to read (can vary in size depending on define)
375*4882a593Smuzhiyun *
376*4882a593Smuzhiyun * start: ptr to start block (only used for storage devices, ignored for
377*4882a593Smuzhiyun * network)
378*4882a593Smuzhiyun *
379*4882a593Smuzhiyun * act_len: ptr to where to put the len actually read
380*4882a593Smuzhiyun */
API_dev_read(va_list ap)381*4882a593Smuzhiyun static int API_dev_read(va_list ap)
382*4882a593Smuzhiyun {
383*4882a593Smuzhiyun struct device_info *di;
384*4882a593Smuzhiyun void *buf;
385*4882a593Smuzhiyun lbasize_t *len_stor, *act_len_stor;
386*4882a593Smuzhiyun lbastart_t *start;
387*4882a593Smuzhiyun int *len_net, *act_len_net;
388*4882a593Smuzhiyun
389*4882a593Smuzhiyun /* 1. arg is ptr to the device_info struct */
390*4882a593Smuzhiyun di = (struct device_info *)va_arg(ap, uintptr_t);
391*4882a593Smuzhiyun if (di == NULL)
392*4882a593Smuzhiyun return API_EINVAL;
393*4882a593Smuzhiyun
394*4882a593Smuzhiyun /* XXX should we check if device is open? i.e. the ->state ? */
395*4882a593Smuzhiyun
396*4882a593Smuzhiyun if (di->cookie == NULL)
397*4882a593Smuzhiyun return API_ENODEV;
398*4882a593Smuzhiyun
399*4882a593Smuzhiyun /* 2. arg is ptr to buffer from where to put the read data */
400*4882a593Smuzhiyun buf = (void *)va_arg(ap, uintptr_t);
401*4882a593Smuzhiyun if (buf == NULL)
402*4882a593Smuzhiyun return API_EINVAL;
403*4882a593Smuzhiyun
404*4882a593Smuzhiyun if (di->type & DEV_TYP_STOR) {
405*4882a593Smuzhiyun /* 3. arg - ptr to var with # of blocks to read */
406*4882a593Smuzhiyun len_stor = (lbasize_t *)va_arg(ap, uintptr_t);
407*4882a593Smuzhiyun if (!len_stor)
408*4882a593Smuzhiyun return API_EINVAL;
409*4882a593Smuzhiyun if (*len_stor <= 0)
410*4882a593Smuzhiyun return API_EINVAL;
411*4882a593Smuzhiyun
412*4882a593Smuzhiyun /* 4. arg - ptr to var with start block */
413*4882a593Smuzhiyun start = (lbastart_t *)va_arg(ap, uintptr_t);
414*4882a593Smuzhiyun
415*4882a593Smuzhiyun /* 5. arg - ptr to var where to put the len actually read */
416*4882a593Smuzhiyun act_len_stor = (lbasize_t *)va_arg(ap, uintptr_t);
417*4882a593Smuzhiyun if (!act_len_stor)
418*4882a593Smuzhiyun return API_EINVAL;
419*4882a593Smuzhiyun
420*4882a593Smuzhiyun *act_len_stor = dev_read_stor(di->cookie, buf, *len_stor, *start);
421*4882a593Smuzhiyun
422*4882a593Smuzhiyun } else if (di->type & DEV_TYP_NET) {
423*4882a593Smuzhiyun
424*4882a593Smuzhiyun /* 3. arg points to the var with length of packet to read */
425*4882a593Smuzhiyun len_net = (int *)va_arg(ap, uintptr_t);
426*4882a593Smuzhiyun if (!len_net)
427*4882a593Smuzhiyun return API_EINVAL;
428*4882a593Smuzhiyun if (*len_net <= 0)
429*4882a593Smuzhiyun return API_EINVAL;
430*4882a593Smuzhiyun
431*4882a593Smuzhiyun /* 4. - ptr to var where to put the len actually read */
432*4882a593Smuzhiyun act_len_net = (int *)va_arg(ap, uintptr_t);
433*4882a593Smuzhiyun if (!act_len_net)
434*4882a593Smuzhiyun return API_EINVAL;
435*4882a593Smuzhiyun
436*4882a593Smuzhiyun *act_len_net = dev_read_net(di->cookie, buf, *len_net);
437*4882a593Smuzhiyun
438*4882a593Smuzhiyun } else
439*4882a593Smuzhiyun return API_ENODEV;
440*4882a593Smuzhiyun
441*4882a593Smuzhiyun return 0;
442*4882a593Smuzhiyun }
443*4882a593Smuzhiyun
444*4882a593Smuzhiyun
445*4882a593Smuzhiyun /*
446*4882a593Smuzhiyun * pseudo signature:
447*4882a593Smuzhiyun *
448*4882a593Smuzhiyun * int API_env_get(const char *name, char **value)
449*4882a593Smuzhiyun *
450*4882a593Smuzhiyun * name: ptr to name of env var
451*4882a593Smuzhiyun */
API_env_get(va_list ap)452*4882a593Smuzhiyun static int API_env_get(va_list ap)
453*4882a593Smuzhiyun {
454*4882a593Smuzhiyun char *name, **value;
455*4882a593Smuzhiyun
456*4882a593Smuzhiyun if ((name = (char *)va_arg(ap, uintptr_t)) == NULL)
457*4882a593Smuzhiyun return API_EINVAL;
458*4882a593Smuzhiyun if ((value = (char **)va_arg(ap, uintptr_t)) == NULL)
459*4882a593Smuzhiyun return API_EINVAL;
460*4882a593Smuzhiyun
461*4882a593Smuzhiyun *value = env_get(name);
462*4882a593Smuzhiyun
463*4882a593Smuzhiyun return 0;
464*4882a593Smuzhiyun }
465*4882a593Smuzhiyun
466*4882a593Smuzhiyun /*
467*4882a593Smuzhiyun * pseudo signature:
468*4882a593Smuzhiyun *
469*4882a593Smuzhiyun * int API_env_set(const char *name, const char *value)
470*4882a593Smuzhiyun *
471*4882a593Smuzhiyun * name: ptr to name of env var
472*4882a593Smuzhiyun *
473*4882a593Smuzhiyun * value: ptr to value to be set
474*4882a593Smuzhiyun */
API_env_set(va_list ap)475*4882a593Smuzhiyun static int API_env_set(va_list ap)
476*4882a593Smuzhiyun {
477*4882a593Smuzhiyun char *name, *value;
478*4882a593Smuzhiyun
479*4882a593Smuzhiyun if ((name = (char *)va_arg(ap, uintptr_t)) == NULL)
480*4882a593Smuzhiyun return API_EINVAL;
481*4882a593Smuzhiyun if ((value = (char *)va_arg(ap, uintptr_t)) == NULL)
482*4882a593Smuzhiyun return API_EINVAL;
483*4882a593Smuzhiyun
484*4882a593Smuzhiyun env_set(name, value);
485*4882a593Smuzhiyun
486*4882a593Smuzhiyun return 0;
487*4882a593Smuzhiyun }
488*4882a593Smuzhiyun
489*4882a593Smuzhiyun /*
490*4882a593Smuzhiyun * pseudo signature:
491*4882a593Smuzhiyun *
492*4882a593Smuzhiyun * int API_env_enum(const char *last, char **next)
493*4882a593Smuzhiyun *
494*4882a593Smuzhiyun * last: ptr to name of env var found in last iteration
495*4882a593Smuzhiyun */
API_env_enum(va_list ap)496*4882a593Smuzhiyun static int API_env_enum(va_list ap)
497*4882a593Smuzhiyun {
498*4882a593Smuzhiyun int i, buflen;
499*4882a593Smuzhiyun char *last, **next, *s;
500*4882a593Smuzhiyun ENTRY *match, search;
501*4882a593Smuzhiyun static char *var;
502*4882a593Smuzhiyun
503*4882a593Smuzhiyun last = (char *)va_arg(ap, unsigned long);
504*4882a593Smuzhiyun
505*4882a593Smuzhiyun if ((next = (char **)va_arg(ap, uintptr_t)) == NULL)
506*4882a593Smuzhiyun return API_EINVAL;
507*4882a593Smuzhiyun
508*4882a593Smuzhiyun if (last == NULL) {
509*4882a593Smuzhiyun var = NULL;
510*4882a593Smuzhiyun i = 0;
511*4882a593Smuzhiyun } else {
512*4882a593Smuzhiyun var = strdup(last);
513*4882a593Smuzhiyun s = strchr(var, '=');
514*4882a593Smuzhiyun if (s != NULL)
515*4882a593Smuzhiyun *s = 0;
516*4882a593Smuzhiyun search.key = var;
517*4882a593Smuzhiyun i = hsearch_r(search, FIND, &match, &env_htab, 0);
518*4882a593Smuzhiyun if (i == 0) {
519*4882a593Smuzhiyun i = API_EINVAL;
520*4882a593Smuzhiyun goto done;
521*4882a593Smuzhiyun }
522*4882a593Smuzhiyun }
523*4882a593Smuzhiyun
524*4882a593Smuzhiyun /* match the next entry after i */
525*4882a593Smuzhiyun i = hmatch_r("", i, &match, &env_htab);
526*4882a593Smuzhiyun if (i == 0)
527*4882a593Smuzhiyun goto done;
528*4882a593Smuzhiyun buflen = strlen(match->key) + strlen(match->data) + 2;
529*4882a593Smuzhiyun var = realloc(var, buflen);
530*4882a593Smuzhiyun snprintf(var, buflen, "%s=%s", match->key, match->data);
531*4882a593Smuzhiyun *next = var;
532*4882a593Smuzhiyun return 0;
533*4882a593Smuzhiyun
534*4882a593Smuzhiyun done:
535*4882a593Smuzhiyun free(var);
536*4882a593Smuzhiyun var = NULL;
537*4882a593Smuzhiyun *next = NULL;
538*4882a593Smuzhiyun return i;
539*4882a593Smuzhiyun }
540*4882a593Smuzhiyun
541*4882a593Smuzhiyun /*
542*4882a593Smuzhiyun * pseudo signature:
543*4882a593Smuzhiyun *
544*4882a593Smuzhiyun * int API_display_get_info(int type, struct display_info *di)
545*4882a593Smuzhiyun */
API_display_get_info(va_list ap)546*4882a593Smuzhiyun static int API_display_get_info(va_list ap)
547*4882a593Smuzhiyun {
548*4882a593Smuzhiyun int type;
549*4882a593Smuzhiyun struct display_info *di;
550*4882a593Smuzhiyun
551*4882a593Smuzhiyun type = va_arg(ap, int);
552*4882a593Smuzhiyun di = va_arg(ap, struct display_info *);
553*4882a593Smuzhiyun
554*4882a593Smuzhiyun return display_get_info(type, di);
555*4882a593Smuzhiyun }
556*4882a593Smuzhiyun
557*4882a593Smuzhiyun /*
558*4882a593Smuzhiyun * pseudo signature:
559*4882a593Smuzhiyun *
560*4882a593Smuzhiyun * int API_display_draw_bitmap(ulong bitmap, int x, int y)
561*4882a593Smuzhiyun */
API_display_draw_bitmap(va_list ap)562*4882a593Smuzhiyun static int API_display_draw_bitmap(va_list ap)
563*4882a593Smuzhiyun {
564*4882a593Smuzhiyun ulong bitmap;
565*4882a593Smuzhiyun int x, y;
566*4882a593Smuzhiyun
567*4882a593Smuzhiyun bitmap = va_arg(ap, ulong);
568*4882a593Smuzhiyun x = va_arg(ap, int);
569*4882a593Smuzhiyun y = va_arg(ap, int);
570*4882a593Smuzhiyun
571*4882a593Smuzhiyun return display_draw_bitmap(bitmap, x, y);
572*4882a593Smuzhiyun }
573*4882a593Smuzhiyun
574*4882a593Smuzhiyun /*
575*4882a593Smuzhiyun * pseudo signature:
576*4882a593Smuzhiyun *
577*4882a593Smuzhiyun * void API_display_clear(void)
578*4882a593Smuzhiyun */
API_display_clear(va_list ap)579*4882a593Smuzhiyun static int API_display_clear(va_list ap)
580*4882a593Smuzhiyun {
581*4882a593Smuzhiyun display_clear();
582*4882a593Smuzhiyun return 0;
583*4882a593Smuzhiyun }
584*4882a593Smuzhiyun
585*4882a593Smuzhiyun static cfp_t calls_table[API_MAXCALL] = { NULL, };
586*4882a593Smuzhiyun
587*4882a593Smuzhiyun /*
588*4882a593Smuzhiyun * The main syscall entry point - this is not reentrant, only one call is
589*4882a593Smuzhiyun * serviced until finished.
590*4882a593Smuzhiyun *
591*4882a593Smuzhiyun * e.g. syscall(1, int *, u_int32_t, u_int32_t, u_int32_t, u_int32_t);
592*4882a593Smuzhiyun *
593*4882a593Smuzhiyun * call: syscall number
594*4882a593Smuzhiyun *
595*4882a593Smuzhiyun * retval: points to the return value placeholder, this is the place the
596*4882a593Smuzhiyun * syscall puts its return value, if NULL the caller does not
597*4882a593Smuzhiyun * expect a return value
598*4882a593Smuzhiyun *
599*4882a593Smuzhiyun * ... syscall arguments (variable number)
600*4882a593Smuzhiyun *
601*4882a593Smuzhiyun * returns: 0 if the call not found, 1 if serviced
602*4882a593Smuzhiyun */
syscall(int call,int * retval,...)603*4882a593Smuzhiyun int syscall(int call, int *retval, ...)
604*4882a593Smuzhiyun {
605*4882a593Smuzhiyun va_list ap;
606*4882a593Smuzhiyun int rv;
607*4882a593Smuzhiyun
608*4882a593Smuzhiyun if (call < 0 || call >= calls_no) {
609*4882a593Smuzhiyun debugf("invalid call #%d\n", call);
610*4882a593Smuzhiyun return 0;
611*4882a593Smuzhiyun }
612*4882a593Smuzhiyun
613*4882a593Smuzhiyun if (calls_table[call] == NULL) {
614*4882a593Smuzhiyun debugf("syscall #%d does not have a handler\n", call);
615*4882a593Smuzhiyun return 0;
616*4882a593Smuzhiyun }
617*4882a593Smuzhiyun
618*4882a593Smuzhiyun va_start(ap, retval);
619*4882a593Smuzhiyun rv = calls_table[call](ap);
620*4882a593Smuzhiyun if (retval != NULL)
621*4882a593Smuzhiyun *retval = rv;
622*4882a593Smuzhiyun
623*4882a593Smuzhiyun return 1;
624*4882a593Smuzhiyun }
625*4882a593Smuzhiyun
api_init(void)626*4882a593Smuzhiyun void api_init(void)
627*4882a593Smuzhiyun {
628*4882a593Smuzhiyun struct api_signature *sig;
629*4882a593Smuzhiyun
630*4882a593Smuzhiyun /* TODO put this into linker set one day... */
631*4882a593Smuzhiyun calls_table[API_RSVD] = NULL;
632*4882a593Smuzhiyun calls_table[API_GETC] = &API_getc;
633*4882a593Smuzhiyun calls_table[API_PUTC] = &API_putc;
634*4882a593Smuzhiyun calls_table[API_TSTC] = &API_tstc;
635*4882a593Smuzhiyun calls_table[API_PUTS] = &API_puts;
636*4882a593Smuzhiyun calls_table[API_RESET] = &API_reset;
637*4882a593Smuzhiyun calls_table[API_GET_SYS_INFO] = &API_get_sys_info;
638*4882a593Smuzhiyun calls_table[API_UDELAY] = &API_udelay;
639*4882a593Smuzhiyun calls_table[API_GET_TIMER] = &API_get_timer;
640*4882a593Smuzhiyun calls_table[API_DEV_ENUM] = &API_dev_enum;
641*4882a593Smuzhiyun calls_table[API_DEV_OPEN] = &API_dev_open;
642*4882a593Smuzhiyun calls_table[API_DEV_CLOSE] = &API_dev_close;
643*4882a593Smuzhiyun calls_table[API_DEV_READ] = &API_dev_read;
644*4882a593Smuzhiyun calls_table[API_DEV_WRITE] = &API_dev_write;
645*4882a593Smuzhiyun calls_table[API_ENV_GET] = &API_env_get;
646*4882a593Smuzhiyun calls_table[API_ENV_SET] = &API_env_set;
647*4882a593Smuzhiyun calls_table[API_ENV_ENUM] = &API_env_enum;
648*4882a593Smuzhiyun calls_table[API_DISPLAY_GET_INFO] = &API_display_get_info;
649*4882a593Smuzhiyun calls_table[API_DISPLAY_DRAW_BITMAP] = &API_display_draw_bitmap;
650*4882a593Smuzhiyun calls_table[API_DISPLAY_CLEAR] = &API_display_clear;
651*4882a593Smuzhiyun calls_no = API_MAXCALL;
652*4882a593Smuzhiyun
653*4882a593Smuzhiyun debugf("API initialized with %d calls\n", calls_no);
654*4882a593Smuzhiyun
655*4882a593Smuzhiyun dev_stor_init();
656*4882a593Smuzhiyun
657*4882a593Smuzhiyun /*
658*4882a593Smuzhiyun * Produce the signature so the API consumers can find it
659*4882a593Smuzhiyun */
660*4882a593Smuzhiyun sig = malloc(sizeof(struct api_signature));
661*4882a593Smuzhiyun if (sig == NULL) {
662*4882a593Smuzhiyun printf("API: could not allocate memory for the signature!\n");
663*4882a593Smuzhiyun return;
664*4882a593Smuzhiyun }
665*4882a593Smuzhiyun
666*4882a593Smuzhiyun env_set_hex("api_address", (unsigned long)sig);
667*4882a593Smuzhiyun debugf("API sig @ 0x%lX\n", (unsigned long)sig);
668*4882a593Smuzhiyun memcpy(sig->magic, API_SIG_MAGIC, 8);
669*4882a593Smuzhiyun sig->version = API_SIG_VERSION;
670*4882a593Smuzhiyun sig->syscall = &syscall;
671*4882a593Smuzhiyun sig->checksum = 0;
672*4882a593Smuzhiyun sig->checksum = crc32(0, (unsigned char *)sig,
673*4882a593Smuzhiyun sizeof(struct api_signature));
674*4882a593Smuzhiyun debugf("syscall entry: 0x%lX\n", (unsigned long)sig->syscall);
675*4882a593Smuzhiyun }
676*4882a593Smuzhiyun
platform_set_mr(struct sys_info * si,unsigned long start,unsigned long size,int flags)677*4882a593Smuzhiyun void platform_set_mr(struct sys_info *si, unsigned long start, unsigned long size,
678*4882a593Smuzhiyun int flags)
679*4882a593Smuzhiyun {
680*4882a593Smuzhiyun int i;
681*4882a593Smuzhiyun
682*4882a593Smuzhiyun if (!si->mr || !size || (flags == 0))
683*4882a593Smuzhiyun return;
684*4882a593Smuzhiyun
685*4882a593Smuzhiyun /* find free slot */
686*4882a593Smuzhiyun for (i = 0; i < si->mr_no; i++)
687*4882a593Smuzhiyun if (si->mr[i].flags == 0) {
688*4882a593Smuzhiyun /* insert new mem region */
689*4882a593Smuzhiyun si->mr[i].start = start;
690*4882a593Smuzhiyun si->mr[i].size = size;
691*4882a593Smuzhiyun si->mr[i].flags = flags;
692*4882a593Smuzhiyun return;
693*4882a593Smuzhiyun }
694*4882a593Smuzhiyun }
695