blob: b892c5c278aecc68274ab705d5c9ca1af207d468 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Rafal Jaworowskia19be782008-01-09 19:39:36 +01002/*
3 * (C) Copyright 2007 Semihalf
4 *
5 * Written by: Rafal Jaworowski <raj@semihalf.com>
Rafal Jaworowskia19be782008-01-09 19:39:36 +01006 */
7
8#include <config.h>
Rafal Jaworowskia19be782008-01-09 19:39:36 +01009#include <command.h>
Simon Glass313112a2019-08-01 09:46:46 -060010#include <env.h>
Rafal Jaworowskia19be782008-01-09 19:39:36 +010011#include <malloc.h>
Tom Rinidec7ea02024-05-20 13:35:03 -060012#include <time.h>
Simon Glass9d1f6192019-08-02 09:44:25 -060013#include <env_internal.h>
Tom Rinidec7ea02024-05-20 13:35:03 -060014#include <vsprintf.h>
Simon Glassdbd79542020-05-10 11:40:11 -060015#include <linux/delay.h>
Tom Rinidec7ea02024-05-20 13:35:03 -060016#include <linux/errno.h>
Rafal Jaworowskia19be782008-01-09 19:39:36 +010017#include <linux/types.h>
18#include <api_public.h>
Simon Glass48b6c6b2019-11-14 12:57:16 -070019#include <u-boot/crc.h>
Rafal Jaworowskia19be782008-01-09 19:39:36 +010020
21#include "api_private.h"
22
23#define DEBUG
24#undef DEBUG
25
Rafal Jaworowskia19be782008-01-09 19:39:36 +010026/*****************************************************************************
27 *
28 * This is the API core.
29 *
30 * API_ functions are part of U-Boot code and constitute the lowest level
31 * calls:
32 *
33 * - they know what values they need as arguments
34 * - their direct return value pertains to the API_ "shell" itself (0 on
35 * success, some error code otherwise)
36 * - if the call returns a value it is buried within arguments
37 *
38 ****************************************************************************/
39
40#ifdef DEBUG
41#define debugf(fmt, args...) do { printf("%s(): ", __func__); printf(fmt, ##args); } while (0)
42#else
43#define debugf(fmt, args...)
44#endif
45
46typedef int (*cfp_t)(va_list argp);
47
48static int calls_no;
49
50/*
51 * pseudo signature:
52 *
53 * int API_getc(int *c)
54 */
55static int API_getc(va_list ap)
56{
57 int *c;
58
Stanislav Galabov10c7a572016-02-17 15:23:31 +020059 if ((c = (int *)va_arg(ap, uintptr_t)) == NULL)
Rafal Jaworowskia19be782008-01-09 19:39:36 +010060 return API_EINVAL;
61
Heinrich Schuchardtc4954fb2020-10-07 18:11:48 +020062 *c = getchar();
Rafal Jaworowskia19be782008-01-09 19:39:36 +010063 return 0;
64}
65
66/*
67 * pseudo signature:
68 *
69 * int API_tstc(int *c)
70 */
71static int API_tstc(va_list ap)
72{
73 int *t;
74
Stanislav Galabov10c7a572016-02-17 15:23:31 +020075 if ((t = (int *)va_arg(ap, uintptr_t)) == NULL)
Rafal Jaworowskia19be782008-01-09 19:39:36 +010076 return API_EINVAL;
77
78 *t = tstc();
79 return 0;
80}
81
82/*
83 * pseudo signature:
84 *
85 * int API_putc(char *ch)
86 */
87static int API_putc(va_list ap)
88{
89 char *c;
90
Stanislav Galabov10c7a572016-02-17 15:23:31 +020091 if ((c = (char *)va_arg(ap, uintptr_t)) == NULL)
Rafal Jaworowskia19be782008-01-09 19:39:36 +010092 return API_EINVAL;
93
94 putc(*c);
95 return 0;
96}
97
98/*
99 * pseudo signature:
100 *
101 * int API_puts(char **s)
102 */
103static int API_puts(va_list ap)
104{
105 char *s;
106
Stanislav Galabov10c7a572016-02-17 15:23:31 +0200107 if ((s = (char *)va_arg(ap, uintptr_t)) == NULL)
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100108 return API_EINVAL;
109
110 puts(s);
111 return 0;
112}
113
114/*
115 * pseudo signature:
116 *
117 * int API_reset(void)
118 */
119static int API_reset(va_list ap)
120{
121 do_reset(NULL, 0, 0, NULL);
122
123 /* NOT REACHED */
124 return 0;
125}
126
127/*
128 * pseudo signature:
129 *
130 * int API_get_sys_info(struct sys_info *si)
131 *
132 * fill out the sys_info struct containing selected parameters about the
133 * machine
134 */
135static int API_get_sys_info(va_list ap)
136{
137 struct sys_info *si;
138
Stanislav Galabov10c7a572016-02-17 15:23:31 +0200139 si = (struct sys_info *)va_arg(ap, uintptr_t);
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100140 if (si == NULL)
141 return API_ENOMEM;
142
143 return (platform_sys_info(si)) ? 0 : API_ENODEV;
144}
145
146/*
147 * pseudo signature:
148 *
149 * int API_udelay(unsigned long *udelay)
150 */
151static int API_udelay(va_list ap)
152{
153 unsigned long *d;
154
Stanislav Galabov10c7a572016-02-17 15:23:31 +0200155 if ((d = (unsigned long *)va_arg(ap, unsigned long)) == NULL)
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100156 return API_EINVAL;
157
158 udelay(*d);
159 return 0;
160}
161
162/*
163 * pseudo signature:
164 *
165 * int API_get_timer(unsigned long *current, unsigned long *base)
166 */
167static int API_get_timer(va_list ap)
168{
169 unsigned long *base, *cur;
170
Stanislav Galabov10c7a572016-02-17 15:23:31 +0200171 cur = (unsigned long *)va_arg(ap, unsigned long);
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100172 if (cur == NULL)
173 return API_EINVAL;
174
Stanislav Galabov10c7a572016-02-17 15:23:31 +0200175 base = (unsigned long *)va_arg(ap, unsigned long);
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100176 if (base == NULL)
177 return API_EINVAL;
178
179 *cur = get_timer(*base);
180 return 0;
181}
182
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100183/*****************************************************************************
184 *
185 * pseudo signature:
186 *
187 * int API_dev_enum(struct device_info *)
188 *
189 *
190 * cookies uniqely identify the previously enumerated device instance and
191 * provide a hint for what to inspect in current enum iteration:
192 *
193 * - net: &eth_device struct address from list pointed to by eth_devices
194 *
Simon Glasse3394752016-02-29 15:25:34 -0700195 * - storage: struct blk_desc struct address from &ide_dev_desc[n],
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100196 * &scsi_dev_desc[n] and similar tables
197 *
198 ****************************************************************************/
199
200static int API_dev_enum(va_list ap)
201{
202 struct device_info *di;
203
204 /* arg is ptr to the device_info struct we are going to fill out */
Stanislav Galabov10c7a572016-02-17 15:23:31 +0200205 di = (struct device_info *)va_arg(ap, uintptr_t);
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100206 if (di == NULL)
207 return API_EINVAL;
208
209 if (di->cookie == NULL) {
210 /* start over - clean up enumeration */
211 dev_enum_reset(); /* XXX shouldn't the name contain 'stor'? */
212 debugf("RESTART ENUM\n");
Wolfgang Denk545b06a2008-01-10 00:55:14 +0100213
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100214 /* net device enumeration first */
215 if (dev_enum_net(di))
216 return 0;
217 }
218
219 /*
220 * The hidden assumption is there can only be one active network
221 * device and it is identified upon enumeration (re)start, so there's
222 * no point in trying to find network devices in other cases than the
223 * (re)start and hence the 'next' device can only be storage
224 */
225 if (!dev_enum_storage(di))
226 /* make sure we mark there are no more devices */
227 di->cookie = NULL;
228
229 return 0;
230}
231
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100232static int API_dev_open(va_list ap)
233{
234 struct device_info *di;
235 int err = 0;
236
237 /* arg is ptr to the device_info struct */
Stanislav Galabov10c7a572016-02-17 15:23:31 +0200238 di = (struct device_info *)va_arg(ap, uintptr_t);
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100239 if (di == NULL)
240 return API_EINVAL;
241
242 /* Allow only one consumer of the device at a time */
243 if (di->state == DEV_STA_OPEN)
244 return API_EBUSY;
245
246 if (di->cookie == NULL)
247 return API_ENODEV;
248
249 if (di->type & DEV_TYP_STOR)
250 err = dev_open_stor(di->cookie);
251
252 else if (di->type & DEV_TYP_NET)
253 err = dev_open_net(di->cookie);
254 else
255 err = API_ENODEV;
256
257 if (!err)
258 di->state = DEV_STA_OPEN;
259
260 return err;
261}
262
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100263static int API_dev_close(va_list ap)
264{
265 struct device_info *di;
266 int err = 0;
267
268 /* arg is ptr to the device_info struct */
Stanislav Galabov10c7a572016-02-17 15:23:31 +0200269 di = (struct device_info *)va_arg(ap, uintptr_t);
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100270 if (di == NULL)
271 return API_EINVAL;
272
273 if (di->state == DEV_STA_CLOSED)
274 return 0;
275
276 if (di->cookie == NULL)
277 return API_ENODEV;
278
279 if (di->type & DEV_TYP_STOR)
280 err = dev_close_stor(di->cookie);
281
282 else if (di->type & DEV_TYP_NET)
283 err = dev_close_net(di->cookie);
284 else
285 /*
286 * In case of unknown device we cannot change its state, so
287 * only return error code
288 */
289 err = API_ENODEV;
290
291 if (!err)
292 di->state = DEV_STA_CLOSED;
293
294 return err;
295}
296
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100297/*
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100298 * pseudo signature:
299 *
300 * int API_dev_write(
301 * struct device_info *di,
302 * void *buf,
Cristian Ciocaltea29f2ace2019-01-12 02:03:15 +0200303 * int *len,
304 * unsigned long *start
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100305 * )
306 *
307 * buf: ptr to buffer from where to get the data to send
308 *
Cristian Ciocaltea29f2ace2019-01-12 02:03:15 +0200309 * len: ptr to length to be read
310 * - network: len of packet to be sent (in bytes)
311 * - storage: # of blocks to write (can vary in size depending on define)
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100312 *
Cristian Ciocaltea29f2ace2019-01-12 02:03:15 +0200313 * start: ptr to start block (only used for storage devices, ignored for
314 * network)
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100315 */
316static int API_dev_write(va_list ap)
317{
318 struct device_info *di;
319 void *buf;
Cristian Ciocaltea29f2ace2019-01-12 02:03:15 +0200320 lbasize_t *len_stor, act_len_stor;
321 lbastart_t *start;
322 int *len_net;
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100323 int err = 0;
324
325 /* 1. arg is ptr to the device_info struct */
Stanislav Galabov10c7a572016-02-17 15:23:31 +0200326 di = (struct device_info *)va_arg(ap, uintptr_t);
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100327 if (di == NULL)
328 return API_EINVAL;
329
330 /* XXX should we check if device is open? i.e. the ->state ? */
331
332 if (di->cookie == NULL)
333 return API_ENODEV;
334
335 /* 2. arg is ptr to buffer from where to get data to write */
Stanislav Galabov10c7a572016-02-17 15:23:31 +0200336 buf = (void *)va_arg(ap, uintptr_t);
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100337 if (buf == NULL)
338 return API_EINVAL;
339
Cristian Ciocaltea29f2ace2019-01-12 02:03:15 +0200340 if (di->type & DEV_TYP_STOR) {
341 /* 3. arg - ptr to var with # of blocks to write */
342 len_stor = (lbasize_t *)va_arg(ap, uintptr_t);
343 if (!len_stor)
344 return API_EINVAL;
345 if (*len_stor <= 0)
346 return API_EINVAL;
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100347
Cristian Ciocaltea29f2ace2019-01-12 02:03:15 +0200348 /* 4. arg - ptr to var with start block */
349 start = (lbastart_t *)va_arg(ap, uintptr_t);
350
351 act_len_stor = dev_write_stor(di->cookie, buf, *len_stor, *start);
352 if (act_len_stor != *len_stor) {
353 debugf("write @ %llu: done %llu out of %llu blocks",
354 (uint64_t)blk, (uint64_t)act_len_stor,
355 (uint64_t)len_stor);
356 return API_EIO;
357 }
358
359 } else if (di->type & DEV_TYP_NET) {
360 /* 3. arg points to the var with length of packet to write */
361 len_net = (int *)va_arg(ap, uintptr_t);
362 if (!len_net)
363 return API_EINVAL;
364 if (*len_net <= 0)
365 return API_EINVAL;
366
367 err = dev_write_net(di->cookie, buf, *len_net);
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100368
Cristian Ciocaltea29f2ace2019-01-12 02:03:15 +0200369 } else
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100370 err = API_ENODEV;
371
372 return err;
373}
374
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100375/*
376 * pseudo signature:
377 *
378 * int API_dev_read(
379 * struct device_info *di,
380 * void *buf,
381 * size_t *len,
382 * unsigned long *start
383 * size_t *act_len
384 * )
385 *
386 * buf: ptr to buffer where to put the read data
387 *
388 * len: ptr to length to be read
389 * - network: len of packet to read (in bytes)
390 * - storage: # of blocks to read (can vary in size depending on define)
391 *
392 * start: ptr to start block (only used for storage devices, ignored for
393 * network)
394 *
395 * act_len: ptr to where to put the len actually read
396 */
397static int API_dev_read(va_list ap)
398{
399 struct device_info *di;
400 void *buf;
401 lbasize_t *len_stor, *act_len_stor;
402 lbastart_t *start;
403 int *len_net, *act_len_net;
404
405 /* 1. arg is ptr to the device_info struct */
Stanislav Galabov10c7a572016-02-17 15:23:31 +0200406 di = (struct device_info *)va_arg(ap, uintptr_t);
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100407 if (di == NULL)
408 return API_EINVAL;
409
410 /* XXX should we check if device is open? i.e. the ->state ? */
411
412 if (di->cookie == NULL)
413 return API_ENODEV;
414
415 /* 2. arg is ptr to buffer from where to put the read data */
Stanislav Galabov10c7a572016-02-17 15:23:31 +0200416 buf = (void *)va_arg(ap, uintptr_t);
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100417 if (buf == NULL)
418 return API_EINVAL;
419
420 if (di->type & DEV_TYP_STOR) {
421 /* 3. arg - ptr to var with # of blocks to read */
Stanislav Galabov10c7a572016-02-17 15:23:31 +0200422 len_stor = (lbasize_t *)va_arg(ap, uintptr_t);
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100423 if (!len_stor)
424 return API_EINVAL;
425 if (*len_stor <= 0)
426 return API_EINVAL;
427
428 /* 4. arg - ptr to var with start block */
Stanislav Galabov10c7a572016-02-17 15:23:31 +0200429 start = (lbastart_t *)va_arg(ap, uintptr_t);
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100430
431 /* 5. arg - ptr to var where to put the len actually read */
Stanislav Galabov10c7a572016-02-17 15:23:31 +0200432 act_len_stor = (lbasize_t *)va_arg(ap, uintptr_t);
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100433 if (!act_len_stor)
434 return API_EINVAL;
435
436 *act_len_stor = dev_read_stor(di->cookie, buf, *len_stor, *start);
437
438 } else if (di->type & DEV_TYP_NET) {
439
440 /* 3. arg points to the var with length of packet to read */
Stanislav Galabov10c7a572016-02-17 15:23:31 +0200441 len_net = (int *)va_arg(ap, uintptr_t);
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100442 if (!len_net)
443 return API_EINVAL;
444 if (*len_net <= 0)
445 return API_EINVAL;
446
447 /* 4. - ptr to var where to put the len actually read */
Stanislav Galabov10c7a572016-02-17 15:23:31 +0200448 act_len_net = (int *)va_arg(ap, uintptr_t);
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100449 if (!act_len_net)
450 return API_EINVAL;
451
452 *act_len_net = dev_read_net(di->cookie, buf, *len_net);
453
454 } else
455 return API_ENODEV;
456
457 return 0;
458}
459
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100460/*
461 * pseudo signature:
462 *
463 * int API_env_get(const char *name, char **value)
464 *
465 * name: ptr to name of env var
466 */
467static int API_env_get(va_list ap)
468{
469 char *name, **value;
470
Stanislav Galabov10c7a572016-02-17 15:23:31 +0200471 if ((name = (char *)va_arg(ap, uintptr_t)) == NULL)
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100472 return API_EINVAL;
Stanislav Galabov10c7a572016-02-17 15:23:31 +0200473 if ((value = (char **)va_arg(ap, uintptr_t)) == NULL)
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100474 return API_EINVAL;
475
Simon Glass64b723f2017-08-03 12:22:12 -0600476 *value = env_get(name);
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100477
478 return 0;
479}
480
481/*
482 * pseudo signature:
483 *
484 * int API_env_set(const char *name, const char *value)
485 *
486 * name: ptr to name of env var
487 *
488 * value: ptr to value to be set
489 */
490static int API_env_set(va_list ap)
491{
492 char *name, *value;
493
Stanislav Galabov10c7a572016-02-17 15:23:31 +0200494 if ((name = (char *)va_arg(ap, uintptr_t)) == NULL)
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100495 return API_EINVAL;
Stanislav Galabov10c7a572016-02-17 15:23:31 +0200496 if ((value = (char *)va_arg(ap, uintptr_t)) == NULL)
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100497 return API_EINVAL;
498
Simon Glass6a38e412017-08-03 12:22:09 -0600499 env_set(name, value);
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100500
501 return 0;
502}
503
504/*
505 * pseudo signature:
506 *
507 * int API_env_enum(const char *last, char **next)
508 *
509 * last: ptr to name of env var found in last iteration
510 */
511static int API_env_enum(va_list ap)
512{
Emmanuel Vadotc4971b92016-12-26 18:57:56 +0100513 int i, buflen;
514 char *last, **next, *s;
Simon Glass1a236862019-08-02 09:44:18 -0600515 struct env_entry *match, search;
Emmanuel Vadotc4971b92016-12-26 18:57:56 +0100516 static char *var;
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100517
Stanislav Galabov10c7a572016-02-17 15:23:31 +0200518 last = (char *)va_arg(ap, unsigned long);
Wolfgang Denk545b06a2008-01-10 00:55:14 +0100519
Stanislav Galabov10c7a572016-02-17 15:23:31 +0200520 if ((next = (char **)va_arg(ap, uintptr_t)) == NULL)
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100521 return API_EINVAL;
522
Emmanuel Vadotc4971b92016-12-26 18:57:56 +0100523 if (last == NULL) {
524 var = NULL;
525 i = 0;
526 } else {
527 var = strdup(last);
528 s = strchr(var, '=');
529 if (s != NULL)
530 *s = 0;
531 search.key = var;
Simon Glass63a2f572019-08-01 09:47:09 -0600532 i = hsearch_r(search, ENV_FIND, &match, &env_htab, 0);
Emmanuel Vadotc4971b92016-12-26 18:57:56 +0100533 if (i == 0) {
534 i = API_EINVAL;
535 goto done;
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100536 }
537 }
538
Emmanuel Vadotc4971b92016-12-26 18:57:56 +0100539 /* match the next entry after i */
540 i = hmatch_r("", i, &match, &env_htab);
541 if (i == 0)
542 goto done;
543 buflen = strlen(match->key) + strlen(match->data) + 2;
544 var = realloc(var, buflen);
545 snprintf(var, buflen, "%s=%s", match->key, match->data);
546 *next = var;
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100547 return 0;
Emmanuel Vadotc4971b92016-12-26 18:57:56 +0100548
549done:
550 free(var);
551 var = NULL;
552 *next = NULL;
553 return i;
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100554}
555
Che-Liang Chiou0d460412011-10-20 23:04:22 +0000556/*
557 * pseudo signature:
558 *
559 * int API_display_get_info(int type, struct display_info *di)
560 */
561static int API_display_get_info(va_list ap)
562{
563 int type;
564 struct display_info *di;
565
566 type = va_arg(ap, int);
567 di = va_arg(ap, struct display_info *);
568
569 return display_get_info(type, di);
570}
571
572/*
573 * pseudo signature:
574 *
575 * int API_display_draw_bitmap(ulong bitmap, int x, int y)
576 */
577static int API_display_draw_bitmap(va_list ap)
578{
579 ulong bitmap;
580 int x, y;
581
582 bitmap = va_arg(ap, ulong);
583 x = va_arg(ap, int);
584 y = va_arg(ap, int);
585
586 return display_draw_bitmap(bitmap, x, y);
587}
588
589/*
590 * pseudo signature:
591 *
592 * void API_display_clear(void)
593 */
594static int API_display_clear(va_list ap)
595{
596 display_clear();
597 return 0;
598}
599
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100600static cfp_t calls_table[API_MAXCALL] = { NULL, };
601
602/*
603 * The main syscall entry point - this is not reentrant, only one call is
604 * serviced until finished.
605 *
606 * e.g. syscall(1, int *, u_int32_t, u_int32_t, u_int32_t, u_int32_t);
Wolfgang Denk545b06a2008-01-10 00:55:14 +0100607 *
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100608 * call: syscall number
609 *
610 * retval: points to the return value placeholder, this is the place the
611 * syscall puts its return value, if NULL the caller does not
612 * expect a return value
613 *
614 * ... syscall arguments (variable number)
615 *
616 * returns: 0 if the call not found, 1 if serviced
617 */
618int syscall(int call, int *retval, ...)
619{
620 va_list ap;
621 int rv;
622
Jean-Christophe PLAGNIOL-VILLARDffaed162008-05-11 23:13:57 +0200623 if (call < 0 || call >= calls_no) {
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100624 debugf("invalid call #%d\n", call);
625 return 0;
626 }
627
628 if (calls_table[call] == NULL) {
629 debugf("syscall #%d does not have a handler\n", call);
630 return 0;
631 }
632
633 va_start(ap, retval);
634 rv = calls_table[call](ap);
635 if (retval != NULL)
636 *retval = rv;
637
638 return 1;
639}
640
Ovidiu Panait4119ea432020-11-28 10:43:16 +0200641int api_init(void)
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100642{
xypron.glpk@gmx.de0a23a732017-07-30 19:54:37 +0200643 struct api_signature *sig;
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100644
645 /* TODO put this into linker set one day... */
646 calls_table[API_RSVD] = NULL;
647 calls_table[API_GETC] = &API_getc;
648 calls_table[API_PUTC] = &API_putc;
649 calls_table[API_TSTC] = &API_tstc;
650 calls_table[API_PUTS] = &API_puts;
651 calls_table[API_RESET] = &API_reset;
652 calls_table[API_GET_SYS_INFO] = &API_get_sys_info;
653 calls_table[API_UDELAY] = &API_udelay;
654 calls_table[API_GET_TIMER] = &API_get_timer;
655 calls_table[API_DEV_ENUM] = &API_dev_enum;
656 calls_table[API_DEV_OPEN] = &API_dev_open;
657 calls_table[API_DEV_CLOSE] = &API_dev_close;
658 calls_table[API_DEV_READ] = &API_dev_read;
659 calls_table[API_DEV_WRITE] = &API_dev_write;
660 calls_table[API_ENV_GET] = &API_env_get;
661 calls_table[API_ENV_SET] = &API_env_set;
662 calls_table[API_ENV_ENUM] = &API_env_enum;
Che-Liang Chiou0d460412011-10-20 23:04:22 +0000663 calls_table[API_DISPLAY_GET_INFO] = &API_display_get_info;
664 calls_table[API_DISPLAY_DRAW_BITMAP] = &API_display_draw_bitmap;
665 calls_table[API_DISPLAY_CLEAR] = &API_display_clear;
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100666 calls_no = API_MAXCALL;
667
668 debugf("API initialized with %d calls\n", calls_no);
669
670 dev_stor_init();
671
672 /*
673 * Produce the signature so the API consumers can find it
674 */
675 sig = malloc(sizeof(struct api_signature));
676 if (sig == NULL) {
677 printf("API: could not allocate memory for the signature!\n");
Ovidiu Panait4119ea432020-11-28 10:43:16 +0200678 return -ENOMEM;
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100679 }
680
Simon Glass4d949a22017-08-03 12:22:10 -0600681 env_set_hex("api_address", (unsigned long)sig);
Stanislav Galabov10c7a572016-02-17 15:23:31 +0200682 debugf("API sig @ 0x%lX\n", (unsigned long)sig);
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100683 memcpy(sig->magic, API_SIG_MAGIC, 8);
684 sig->version = API_SIG_VERSION;
685 sig->syscall = &syscall;
686 sig->checksum = 0;
687 sig->checksum = crc32(0, (unsigned char *)sig,
688 sizeof(struct api_signature));
Stanislav Galabov10c7a572016-02-17 15:23:31 +0200689 debugf("syscall entry: 0x%lX\n", (unsigned long)sig->syscall);
Ovidiu Panait4119ea432020-11-28 10:43:16 +0200690
691 return 0;
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100692}
693
694void platform_set_mr(struct sys_info *si, unsigned long start, unsigned long size,
695 int flags)
696{
697 int i;
698
699 if (!si->mr || !size || (flags == 0))
700 return;
Wolfgang Denk545b06a2008-01-10 00:55:14 +0100701
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100702 /* find free slot */
703 for (i = 0; i < si->mr_no; i++)
704 if (si->mr[i].flags == 0) {
705 /* insert new mem region */
706 si->mr[i].start = start;
707 si->mr[i].size = size;
708 si->mr[i].flags = flags;
709 return;
710 }
711}