blob: d22132f62fe336dee9da10c4f93bd5ed9a687657 [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
183
184/*****************************************************************************
185 *
186 * pseudo signature:
187 *
188 * int API_dev_enum(struct device_info *)
189 *
190 *
191 * cookies uniqely identify the previously enumerated device instance and
192 * provide a hint for what to inspect in current enum iteration:
193 *
194 * - net: &eth_device struct address from list pointed to by eth_devices
195 *
Simon Glasse3394752016-02-29 15:25:34 -0700196 * - storage: struct blk_desc struct address from &ide_dev_desc[n],
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100197 * &scsi_dev_desc[n] and similar tables
198 *
199 ****************************************************************************/
200
201static int API_dev_enum(va_list ap)
202{
203 struct device_info *di;
204
205 /* arg is ptr to the device_info struct we are going to fill out */
Stanislav Galabov10c7a572016-02-17 15:23:31 +0200206 di = (struct device_info *)va_arg(ap, uintptr_t);
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100207 if (di == NULL)
208 return API_EINVAL;
209
210 if (di->cookie == NULL) {
211 /* start over - clean up enumeration */
212 dev_enum_reset(); /* XXX shouldn't the name contain 'stor'? */
213 debugf("RESTART ENUM\n");
Wolfgang Denk545b06a2008-01-10 00:55:14 +0100214
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100215 /* net device enumeration first */
216 if (dev_enum_net(di))
217 return 0;
218 }
219
220 /*
221 * The hidden assumption is there can only be one active network
222 * device and it is identified upon enumeration (re)start, so there's
223 * no point in trying to find network devices in other cases than the
224 * (re)start and hence the 'next' device can only be storage
225 */
226 if (!dev_enum_storage(di))
227 /* make sure we mark there are no more devices */
228 di->cookie = NULL;
229
230 return 0;
231}
232
233
234static int API_dev_open(va_list ap)
235{
236 struct device_info *di;
237 int err = 0;
238
239 /* arg is ptr to the device_info struct */
Stanislav Galabov10c7a572016-02-17 15:23:31 +0200240 di = (struct device_info *)va_arg(ap, uintptr_t);
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100241 if (di == NULL)
242 return API_EINVAL;
243
244 /* Allow only one consumer of the device at a time */
245 if (di->state == DEV_STA_OPEN)
246 return API_EBUSY;
247
248 if (di->cookie == NULL)
249 return API_ENODEV;
250
251 if (di->type & DEV_TYP_STOR)
252 err = dev_open_stor(di->cookie);
253
254 else if (di->type & DEV_TYP_NET)
255 err = dev_open_net(di->cookie);
256 else
257 err = API_ENODEV;
258
259 if (!err)
260 di->state = DEV_STA_OPEN;
261
262 return err;
263}
264
265
266static int API_dev_close(va_list ap)
267{
268 struct device_info *di;
269 int err = 0;
270
271 /* arg is ptr to the device_info struct */
Stanislav Galabov10c7a572016-02-17 15:23:31 +0200272 di = (struct device_info *)va_arg(ap, uintptr_t);
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100273 if (di == NULL)
274 return API_EINVAL;
275
276 if (di->state == DEV_STA_CLOSED)
277 return 0;
278
279 if (di->cookie == NULL)
280 return API_ENODEV;
281
282 if (di->type & DEV_TYP_STOR)
283 err = dev_close_stor(di->cookie);
284
285 else if (di->type & DEV_TYP_NET)
286 err = dev_close_net(di->cookie);
287 else
288 /*
289 * In case of unknown device we cannot change its state, so
290 * only return error code
291 */
292 err = API_ENODEV;
293
294 if (!err)
295 di->state = DEV_STA_CLOSED;
296
297 return err;
298}
299
300
301/*
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100302 * pseudo signature:
303 *
304 * int API_dev_write(
305 * struct device_info *di,
306 * void *buf,
Cristian Ciocaltea29f2ace2019-01-12 02:03:15 +0200307 * int *len,
308 * unsigned long *start
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100309 * )
310 *
311 * buf: ptr to buffer from where to get the data to send
312 *
Cristian Ciocaltea29f2ace2019-01-12 02:03:15 +0200313 * len: ptr to length to be read
314 * - network: len of packet to be sent (in bytes)
315 * - storage: # of blocks to write (can vary in size depending on define)
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100316 *
Cristian Ciocaltea29f2ace2019-01-12 02:03:15 +0200317 * start: ptr to start block (only used for storage devices, ignored for
318 * network)
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100319 */
320static int API_dev_write(va_list ap)
321{
322 struct device_info *di;
323 void *buf;
Cristian Ciocaltea29f2ace2019-01-12 02:03:15 +0200324 lbasize_t *len_stor, act_len_stor;
325 lbastart_t *start;
326 int *len_net;
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100327 int err = 0;
328
329 /* 1. arg is ptr to the device_info struct */
Stanislav Galabov10c7a572016-02-17 15:23:31 +0200330 di = (struct device_info *)va_arg(ap, uintptr_t);
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100331 if (di == NULL)
332 return API_EINVAL;
333
334 /* XXX should we check if device is open? i.e. the ->state ? */
335
336 if (di->cookie == NULL)
337 return API_ENODEV;
338
339 /* 2. arg is ptr to buffer from where to get data to write */
Stanislav Galabov10c7a572016-02-17 15:23:31 +0200340 buf = (void *)va_arg(ap, uintptr_t);
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100341 if (buf == NULL)
342 return API_EINVAL;
343
Cristian Ciocaltea29f2ace2019-01-12 02:03:15 +0200344 if (di->type & DEV_TYP_STOR) {
345 /* 3. arg - ptr to var with # of blocks to write */
346 len_stor = (lbasize_t *)va_arg(ap, uintptr_t);
347 if (!len_stor)
348 return API_EINVAL;
349 if (*len_stor <= 0)
350 return API_EINVAL;
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100351
Cristian Ciocaltea29f2ace2019-01-12 02:03:15 +0200352 /* 4. arg - ptr to var with start block */
353 start = (lbastart_t *)va_arg(ap, uintptr_t);
354
355 act_len_stor = dev_write_stor(di->cookie, buf, *len_stor, *start);
356 if (act_len_stor != *len_stor) {
357 debugf("write @ %llu: done %llu out of %llu blocks",
358 (uint64_t)blk, (uint64_t)act_len_stor,
359 (uint64_t)len_stor);
360 return API_EIO;
361 }
362
363 } else if (di->type & DEV_TYP_NET) {
364 /* 3. arg points to the var with length of packet to write */
365 len_net = (int *)va_arg(ap, uintptr_t);
366 if (!len_net)
367 return API_EINVAL;
368 if (*len_net <= 0)
369 return API_EINVAL;
370
371 err = dev_write_net(di->cookie, buf, *len_net);
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100372
Cristian Ciocaltea29f2ace2019-01-12 02:03:15 +0200373 } else
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100374 err = API_ENODEV;
375
376 return err;
377}
378
379
380/*
381 * pseudo signature:
382 *
383 * int API_dev_read(
384 * struct device_info *di,
385 * void *buf,
386 * size_t *len,
387 * unsigned long *start
388 * size_t *act_len
389 * )
390 *
391 * buf: ptr to buffer where to put the read data
392 *
393 * len: ptr to length to be read
394 * - network: len of packet to read (in bytes)
395 * - storage: # of blocks to read (can vary in size depending on define)
396 *
397 * start: ptr to start block (only used for storage devices, ignored for
398 * network)
399 *
400 * act_len: ptr to where to put the len actually read
401 */
402static int API_dev_read(va_list ap)
403{
404 struct device_info *di;
405 void *buf;
406 lbasize_t *len_stor, *act_len_stor;
407 lbastart_t *start;
408 int *len_net, *act_len_net;
409
410 /* 1. arg is ptr to the device_info struct */
Stanislav Galabov10c7a572016-02-17 15:23:31 +0200411 di = (struct device_info *)va_arg(ap, uintptr_t);
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100412 if (di == NULL)
413 return API_EINVAL;
414
415 /* XXX should we check if device is open? i.e. the ->state ? */
416
417 if (di->cookie == NULL)
418 return API_ENODEV;
419
420 /* 2. arg is ptr to buffer from where to put the read data */
Stanislav Galabov10c7a572016-02-17 15:23:31 +0200421 buf = (void *)va_arg(ap, uintptr_t);
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100422 if (buf == NULL)
423 return API_EINVAL;
424
425 if (di->type & DEV_TYP_STOR) {
426 /* 3. arg - ptr to var with # of blocks to read */
Stanislav Galabov10c7a572016-02-17 15:23:31 +0200427 len_stor = (lbasize_t *)va_arg(ap, uintptr_t);
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100428 if (!len_stor)
429 return API_EINVAL;
430 if (*len_stor <= 0)
431 return API_EINVAL;
432
433 /* 4. arg - ptr to var with start block */
Stanislav Galabov10c7a572016-02-17 15:23:31 +0200434 start = (lbastart_t *)va_arg(ap, uintptr_t);
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100435
436 /* 5. arg - ptr to var where to put the len actually read */
Stanislav Galabov10c7a572016-02-17 15:23:31 +0200437 act_len_stor = (lbasize_t *)va_arg(ap, uintptr_t);
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100438 if (!act_len_stor)
439 return API_EINVAL;
440
441 *act_len_stor = dev_read_stor(di->cookie, buf, *len_stor, *start);
442
443 } else if (di->type & DEV_TYP_NET) {
444
445 /* 3. arg points to the var with length of packet to read */
Stanislav Galabov10c7a572016-02-17 15:23:31 +0200446 len_net = (int *)va_arg(ap, uintptr_t);
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100447 if (!len_net)
448 return API_EINVAL;
449 if (*len_net <= 0)
450 return API_EINVAL;
451
452 /* 4. - ptr to var where to put the len actually read */
Stanislav Galabov10c7a572016-02-17 15:23:31 +0200453 act_len_net = (int *)va_arg(ap, uintptr_t);
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100454 if (!act_len_net)
455 return API_EINVAL;
456
457 *act_len_net = dev_read_net(di->cookie, buf, *len_net);
458
459 } else
460 return API_ENODEV;
461
462 return 0;
463}
464
465
466/*
467 * pseudo signature:
468 *
469 * int API_env_get(const char *name, char **value)
470 *
471 * name: ptr to name of env var
472 */
473static int API_env_get(va_list ap)
474{
475 char *name, **value;
476
Stanislav Galabov10c7a572016-02-17 15:23:31 +0200477 if ((name = (char *)va_arg(ap, uintptr_t)) == NULL)
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100478 return API_EINVAL;
Stanislav Galabov10c7a572016-02-17 15:23:31 +0200479 if ((value = (char **)va_arg(ap, uintptr_t)) == NULL)
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100480 return API_EINVAL;
481
Simon Glass64b723f2017-08-03 12:22:12 -0600482 *value = env_get(name);
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100483
484 return 0;
485}
486
487/*
488 * pseudo signature:
489 *
490 * int API_env_set(const char *name, const char *value)
491 *
492 * name: ptr to name of env var
493 *
494 * value: ptr to value to be set
495 */
496static int API_env_set(va_list ap)
497{
498 char *name, *value;
499
Stanislav Galabov10c7a572016-02-17 15:23:31 +0200500 if ((name = (char *)va_arg(ap, uintptr_t)) == NULL)
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100501 return API_EINVAL;
Stanislav Galabov10c7a572016-02-17 15:23:31 +0200502 if ((value = (char *)va_arg(ap, uintptr_t)) == NULL)
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100503 return API_EINVAL;
504
Simon Glass6a38e412017-08-03 12:22:09 -0600505 env_set(name, value);
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100506
507 return 0;
508}
509
510/*
511 * pseudo signature:
512 *
513 * int API_env_enum(const char *last, char **next)
514 *
515 * last: ptr to name of env var found in last iteration
516 */
517static int API_env_enum(va_list ap)
518{
Emmanuel Vadotc4971b92016-12-26 18:57:56 +0100519 int i, buflen;
520 char *last, **next, *s;
Simon Glass1a236862019-08-02 09:44:18 -0600521 struct env_entry *match, search;
Emmanuel Vadotc4971b92016-12-26 18:57:56 +0100522 static char *var;
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100523
Stanislav Galabov10c7a572016-02-17 15:23:31 +0200524 last = (char *)va_arg(ap, unsigned long);
Wolfgang Denk545b06a2008-01-10 00:55:14 +0100525
Stanislav Galabov10c7a572016-02-17 15:23:31 +0200526 if ((next = (char **)va_arg(ap, uintptr_t)) == NULL)
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100527 return API_EINVAL;
528
Emmanuel Vadotc4971b92016-12-26 18:57:56 +0100529 if (last == NULL) {
530 var = NULL;
531 i = 0;
532 } else {
533 var = strdup(last);
534 s = strchr(var, '=');
535 if (s != NULL)
536 *s = 0;
537 search.key = var;
Simon Glass63a2f572019-08-01 09:47:09 -0600538 i = hsearch_r(search, ENV_FIND, &match, &env_htab, 0);
Emmanuel Vadotc4971b92016-12-26 18:57:56 +0100539 if (i == 0) {
540 i = API_EINVAL;
541 goto done;
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100542 }
543 }
544
Emmanuel Vadotc4971b92016-12-26 18:57:56 +0100545 /* match the next entry after i */
546 i = hmatch_r("", i, &match, &env_htab);
547 if (i == 0)
548 goto done;
549 buflen = strlen(match->key) + strlen(match->data) + 2;
550 var = realloc(var, buflen);
551 snprintf(var, buflen, "%s=%s", match->key, match->data);
552 *next = var;
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100553 return 0;
Emmanuel Vadotc4971b92016-12-26 18:57:56 +0100554
555done:
556 free(var);
557 var = NULL;
558 *next = NULL;
559 return i;
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100560}
561
Che-Liang Chiou0d460412011-10-20 23:04:22 +0000562/*
563 * pseudo signature:
564 *
565 * int API_display_get_info(int type, struct display_info *di)
566 */
567static int API_display_get_info(va_list ap)
568{
569 int type;
570 struct display_info *di;
571
572 type = va_arg(ap, int);
573 di = va_arg(ap, struct display_info *);
574
575 return display_get_info(type, di);
576}
577
578/*
579 * pseudo signature:
580 *
581 * int API_display_draw_bitmap(ulong bitmap, int x, int y)
582 */
583static int API_display_draw_bitmap(va_list ap)
584{
585 ulong bitmap;
586 int x, y;
587
588 bitmap = va_arg(ap, ulong);
589 x = va_arg(ap, int);
590 y = va_arg(ap, int);
591
592 return display_draw_bitmap(bitmap, x, y);
593}
594
595/*
596 * pseudo signature:
597 *
598 * void API_display_clear(void)
599 */
600static int API_display_clear(va_list ap)
601{
602 display_clear();
603 return 0;
604}
605
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100606static cfp_t calls_table[API_MAXCALL] = { NULL, };
607
608/*
609 * The main syscall entry point - this is not reentrant, only one call is
610 * serviced until finished.
611 *
612 * e.g. syscall(1, int *, u_int32_t, u_int32_t, u_int32_t, u_int32_t);
Wolfgang Denk545b06a2008-01-10 00:55:14 +0100613 *
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100614 * call: syscall number
615 *
616 * retval: points to the return value placeholder, this is the place the
617 * syscall puts its return value, if NULL the caller does not
618 * expect a return value
619 *
620 * ... syscall arguments (variable number)
621 *
622 * returns: 0 if the call not found, 1 if serviced
623 */
624int syscall(int call, int *retval, ...)
625{
626 va_list ap;
627 int rv;
628
Jean-Christophe PLAGNIOL-VILLARDffaed162008-05-11 23:13:57 +0200629 if (call < 0 || call >= calls_no) {
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100630 debugf("invalid call #%d\n", call);
631 return 0;
632 }
633
634 if (calls_table[call] == NULL) {
635 debugf("syscall #%d does not have a handler\n", call);
636 return 0;
637 }
638
639 va_start(ap, retval);
640 rv = calls_table[call](ap);
641 if (retval != NULL)
642 *retval = rv;
643
644 return 1;
645}
646
Ovidiu Panait4119ea432020-11-28 10:43:16 +0200647int api_init(void)
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100648{
xypron.glpk@gmx.de0a23a732017-07-30 19:54:37 +0200649 struct api_signature *sig;
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100650
651 /* TODO put this into linker set one day... */
652 calls_table[API_RSVD] = NULL;
653 calls_table[API_GETC] = &API_getc;
654 calls_table[API_PUTC] = &API_putc;
655 calls_table[API_TSTC] = &API_tstc;
656 calls_table[API_PUTS] = &API_puts;
657 calls_table[API_RESET] = &API_reset;
658 calls_table[API_GET_SYS_INFO] = &API_get_sys_info;
659 calls_table[API_UDELAY] = &API_udelay;
660 calls_table[API_GET_TIMER] = &API_get_timer;
661 calls_table[API_DEV_ENUM] = &API_dev_enum;
662 calls_table[API_DEV_OPEN] = &API_dev_open;
663 calls_table[API_DEV_CLOSE] = &API_dev_close;
664 calls_table[API_DEV_READ] = &API_dev_read;
665 calls_table[API_DEV_WRITE] = &API_dev_write;
666 calls_table[API_ENV_GET] = &API_env_get;
667 calls_table[API_ENV_SET] = &API_env_set;
668 calls_table[API_ENV_ENUM] = &API_env_enum;
Che-Liang Chiou0d460412011-10-20 23:04:22 +0000669 calls_table[API_DISPLAY_GET_INFO] = &API_display_get_info;
670 calls_table[API_DISPLAY_DRAW_BITMAP] = &API_display_draw_bitmap;
671 calls_table[API_DISPLAY_CLEAR] = &API_display_clear;
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100672 calls_no = API_MAXCALL;
673
674 debugf("API initialized with %d calls\n", calls_no);
675
676 dev_stor_init();
677
678 /*
679 * Produce the signature so the API consumers can find it
680 */
681 sig = malloc(sizeof(struct api_signature));
682 if (sig == NULL) {
683 printf("API: could not allocate memory for the signature!\n");
Ovidiu Panait4119ea432020-11-28 10:43:16 +0200684 return -ENOMEM;
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100685 }
686
Simon Glass4d949a22017-08-03 12:22:10 -0600687 env_set_hex("api_address", (unsigned long)sig);
Stanislav Galabov10c7a572016-02-17 15:23:31 +0200688 debugf("API sig @ 0x%lX\n", (unsigned long)sig);
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100689 memcpy(sig->magic, API_SIG_MAGIC, 8);
690 sig->version = API_SIG_VERSION;
691 sig->syscall = &syscall;
692 sig->checksum = 0;
693 sig->checksum = crc32(0, (unsigned char *)sig,
694 sizeof(struct api_signature));
Stanislav Galabov10c7a572016-02-17 15:23:31 +0200695 debugf("syscall entry: 0x%lX\n", (unsigned long)sig->syscall);
Ovidiu Panait4119ea432020-11-28 10:43:16 +0200696
697 return 0;
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100698}
699
700void platform_set_mr(struct sys_info *si, unsigned long start, unsigned long size,
701 int flags)
702{
703 int i;
704
705 if (!si->mr || !size || (flags == 0))
706 return;
Wolfgang Denk545b06a2008-01-10 00:55:14 +0100707
Rafal Jaworowskia19be782008-01-09 19:39:36 +0100708 /* find free slot */
709 for (i = 0; i < si->mr_no; i++)
710 if (si->mr[i].flags == 0) {
711 /* insert new mem region */
712 si->mr[i].start = start;
713 si->mr[i].size = size;
714 si->mr[i].flags = flags;
715 return;
716 }
717}