blob: 89003c161c2fbf58cf147a248b7028f38d0f5dea [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Rafal Jaworowski500856e2008-01-09 19:39:36 +01002/*
3 * (C) Copyright 2007 Semihalf
4 *
5 * Written by: Rafal Jaworowski <raj@semihalf.com>
Rafal Jaworowski500856e2008-01-09 19:39:36 +01006 */
7
8#include <config.h>
Rafal Jaworowski500856e2008-01-09 19:39:36 +01009#include <command.h>
Tom Rinid678a592024-05-18 20:20:43 -060010#include <common.h>
Simon Glassc7694dd2019-08-01 09:46:46 -060011#include <env.h>
Rafal Jaworowski500856e2008-01-09 19:39:36 +010012#include <malloc.h>
Simon Glassf3998fd2019-08-02 09:44:25 -060013#include <env_internal.h>
Simon Glassc05ed002020-05-10 11:40:11 -060014#include <linux/delay.h>
Rafal Jaworowski500856e2008-01-09 19:39:36 +010015#include <linux/types.h>
16#include <api_public.h>
Simon Glass3db71102019-11-14 12:57:16 -070017#include <u-boot/crc.h>
Rafal Jaworowski500856e2008-01-09 19:39:36 +010018
19#include "api_private.h"
20
21#define DEBUG
22#undef DEBUG
23
Rafal Jaworowski500856e2008-01-09 19:39:36 +010024/*****************************************************************************
25 *
26 * This is the API core.
27 *
28 * API_ functions are part of U-Boot code and constitute the lowest level
29 * calls:
30 *
31 * - they know what values they need as arguments
32 * - their direct return value pertains to the API_ "shell" itself (0 on
33 * success, some error code otherwise)
34 * - if the call returns a value it is buried within arguments
35 *
36 ****************************************************************************/
37
38#ifdef DEBUG
39#define debugf(fmt, args...) do { printf("%s(): ", __func__); printf(fmt, ##args); } while (0)
40#else
41#define debugf(fmt, args...)
42#endif
43
44typedef int (*cfp_t)(va_list argp);
45
46static int calls_no;
47
48/*
49 * pseudo signature:
50 *
51 * int API_getc(int *c)
52 */
53static int API_getc(va_list ap)
54{
55 int *c;
56
Stanislav Galabov78757d52016-02-17 15:23:31 +020057 if ((c = (int *)va_arg(ap, uintptr_t)) == NULL)
Rafal Jaworowski500856e2008-01-09 19:39:36 +010058 return API_EINVAL;
59
Heinrich Schuchardtc670aee2020-10-07 18:11:48 +020060 *c = getchar();
Rafal Jaworowski500856e2008-01-09 19:39:36 +010061 return 0;
62}
63
64/*
65 * pseudo signature:
66 *
67 * int API_tstc(int *c)
68 */
69static int API_tstc(va_list ap)
70{
71 int *t;
72
Stanislav Galabov78757d52016-02-17 15:23:31 +020073 if ((t = (int *)va_arg(ap, uintptr_t)) == NULL)
Rafal Jaworowski500856e2008-01-09 19:39:36 +010074 return API_EINVAL;
75
76 *t = tstc();
77 return 0;
78}
79
80/*
81 * pseudo signature:
82 *
83 * int API_putc(char *ch)
84 */
85static int API_putc(va_list ap)
86{
87 char *c;
88
Stanislav Galabov78757d52016-02-17 15:23:31 +020089 if ((c = (char *)va_arg(ap, uintptr_t)) == NULL)
Rafal Jaworowski500856e2008-01-09 19:39:36 +010090 return API_EINVAL;
91
92 putc(*c);
93 return 0;
94}
95
96/*
97 * pseudo signature:
98 *
99 * int API_puts(char **s)
100 */
101static int API_puts(va_list ap)
102{
103 char *s;
104
Stanislav Galabov78757d52016-02-17 15:23:31 +0200105 if ((s = (char *)va_arg(ap, uintptr_t)) == NULL)
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100106 return API_EINVAL;
107
108 puts(s);
109 return 0;
110}
111
112/*
113 * pseudo signature:
114 *
115 * int API_reset(void)
116 */
117static int API_reset(va_list ap)
118{
119 do_reset(NULL, 0, 0, NULL);
120
121 /* NOT REACHED */
122 return 0;
123}
124
125/*
126 * pseudo signature:
127 *
128 * int API_get_sys_info(struct sys_info *si)
129 *
130 * fill out the sys_info struct containing selected parameters about the
131 * machine
132 */
133static int API_get_sys_info(va_list ap)
134{
135 struct sys_info *si;
136
Stanislav Galabov78757d52016-02-17 15:23:31 +0200137 si = (struct sys_info *)va_arg(ap, uintptr_t);
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100138 if (si == NULL)
139 return API_ENOMEM;
140
141 return (platform_sys_info(si)) ? 0 : API_ENODEV;
142}
143
144/*
145 * pseudo signature:
146 *
147 * int API_udelay(unsigned long *udelay)
148 */
149static int API_udelay(va_list ap)
150{
151 unsigned long *d;
152
Stanislav Galabov78757d52016-02-17 15:23:31 +0200153 if ((d = (unsigned long *)va_arg(ap, unsigned long)) == NULL)
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100154 return API_EINVAL;
155
156 udelay(*d);
157 return 0;
158}
159
160/*
161 * pseudo signature:
162 *
163 * int API_get_timer(unsigned long *current, unsigned long *base)
164 */
165static int API_get_timer(va_list ap)
166{
167 unsigned long *base, *cur;
168
Stanislav Galabov78757d52016-02-17 15:23:31 +0200169 cur = (unsigned long *)va_arg(ap, unsigned long);
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100170 if (cur == NULL)
171 return API_EINVAL;
172
Stanislav Galabov78757d52016-02-17 15:23:31 +0200173 base = (unsigned long *)va_arg(ap, unsigned long);
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100174 if (base == NULL)
175 return API_EINVAL;
176
177 *cur = get_timer(*base);
178 return 0;
179}
180
181
182/*****************************************************************************
183 *
184 * pseudo signature:
185 *
186 * int API_dev_enum(struct device_info *)
187 *
188 *
189 * cookies uniqely identify the previously enumerated device instance and
190 * provide a hint for what to inspect in current enum iteration:
191 *
192 * - net: &eth_device struct address from list pointed to by eth_devices
193 *
Simon Glass4101f682016-02-29 15:25:34 -0700194 * - storage: struct blk_desc struct address from &ide_dev_desc[n],
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100195 * &scsi_dev_desc[n] and similar tables
196 *
197 ****************************************************************************/
198
199static int API_dev_enum(va_list ap)
200{
201 struct device_info *di;
202
203 /* arg is ptr to the device_info struct we are going to fill out */
Stanislav Galabov78757d52016-02-17 15:23:31 +0200204 di = (struct device_info *)va_arg(ap, uintptr_t);
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100205 if (di == NULL)
206 return API_EINVAL;
207
208 if (di->cookie == NULL) {
209 /* start over - clean up enumeration */
210 dev_enum_reset(); /* XXX shouldn't the name contain 'stor'? */
211 debugf("RESTART ENUM\n");
Wolfgang Denkd3a65322008-01-10 00:55:14 +0100212
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100213 /* net device enumeration first */
214 if (dev_enum_net(di))
215 return 0;
216 }
217
218 /*
219 * The hidden assumption is there can only be one active network
220 * device and it is identified upon enumeration (re)start, so there's
221 * no point in trying to find network devices in other cases than the
222 * (re)start and hence the 'next' device can only be storage
223 */
224 if (!dev_enum_storage(di))
225 /* make sure we mark there are no more devices */
226 di->cookie = NULL;
227
228 return 0;
229}
230
231
232static 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 Galabov78757d52016-02-17 15:23:31 +0200238 di = (struct device_info *)va_arg(ap, uintptr_t);
Rafal Jaworowski500856e2008-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
263
264static int API_dev_close(va_list ap)
265{
266 struct device_info *di;
267 int err = 0;
268
269 /* arg is ptr to the device_info struct */
Stanislav Galabov78757d52016-02-17 15:23:31 +0200270 di = (struct device_info *)va_arg(ap, uintptr_t);
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100271 if (di == NULL)
272 return API_EINVAL;
273
274 if (di->state == DEV_STA_CLOSED)
275 return 0;
276
277 if (di->cookie == NULL)
278 return API_ENODEV;
279
280 if (di->type & DEV_TYP_STOR)
281 err = dev_close_stor(di->cookie);
282
283 else if (di->type & DEV_TYP_NET)
284 err = dev_close_net(di->cookie);
285 else
286 /*
287 * In case of unknown device we cannot change its state, so
288 * only return error code
289 */
290 err = API_ENODEV;
291
292 if (!err)
293 di->state = DEV_STA_CLOSED;
294
295 return err;
296}
297
298
299/*
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100300 * pseudo signature:
301 *
302 * int API_dev_write(
303 * struct device_info *di,
304 * void *buf,
Cristian Ciocaltea036218a2019-01-12 02:03:15 +0200305 * int *len,
306 * unsigned long *start
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100307 * )
308 *
309 * buf: ptr to buffer from where to get the data to send
310 *
Cristian Ciocaltea036218a2019-01-12 02:03:15 +0200311 * len: ptr to length to be read
312 * - network: len of packet to be sent (in bytes)
313 * - storage: # of blocks to write (can vary in size depending on define)
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100314 *
Cristian Ciocaltea036218a2019-01-12 02:03:15 +0200315 * start: ptr to start block (only used for storage devices, ignored for
316 * network)
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100317 */
318static int API_dev_write(va_list ap)
319{
320 struct device_info *di;
321 void *buf;
Cristian Ciocaltea036218a2019-01-12 02:03:15 +0200322 lbasize_t *len_stor, act_len_stor;
323 lbastart_t *start;
324 int *len_net;
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100325 int err = 0;
326
327 /* 1. arg is ptr to the device_info struct */
Stanislav Galabov78757d52016-02-17 15:23:31 +0200328 di = (struct device_info *)va_arg(ap, uintptr_t);
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100329 if (di == NULL)
330 return API_EINVAL;
331
332 /* XXX should we check if device is open? i.e. the ->state ? */
333
334 if (di->cookie == NULL)
335 return API_ENODEV;
336
337 /* 2. arg is ptr to buffer from where to get data to write */
Stanislav Galabov78757d52016-02-17 15:23:31 +0200338 buf = (void *)va_arg(ap, uintptr_t);
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100339 if (buf == NULL)
340 return API_EINVAL;
341
Cristian Ciocaltea036218a2019-01-12 02:03:15 +0200342 if (di->type & DEV_TYP_STOR) {
343 /* 3. arg - ptr to var with # of blocks to write */
344 len_stor = (lbasize_t *)va_arg(ap, uintptr_t);
345 if (!len_stor)
346 return API_EINVAL;
347 if (*len_stor <= 0)
348 return API_EINVAL;
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100349
Cristian Ciocaltea036218a2019-01-12 02:03:15 +0200350 /* 4. arg - ptr to var with start block */
351 start = (lbastart_t *)va_arg(ap, uintptr_t);
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100352
Cristian Ciocaltea036218a2019-01-12 02:03:15 +0200353 act_len_stor = dev_write_stor(di->cookie, buf, *len_stor, *start);
354 if (act_len_stor != *len_stor) {
355 debugf("write @ %llu: done %llu out of %llu blocks",
356 (uint64_t)blk, (uint64_t)act_len_stor,
357 (uint64_t)len_stor);
358 return API_EIO;
359 }
360
361 } else if (di->type & DEV_TYP_NET) {
362 /* 3. arg points to the var with length of packet to write */
363 len_net = (int *)va_arg(ap, uintptr_t);
364 if (!len_net)
365 return API_EINVAL;
366 if (*len_net <= 0)
367 return API_EINVAL;
368
369 err = dev_write_net(di->cookie, buf, *len_net);
370
371 } else
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100372 err = API_ENODEV;
373
374 return err;
375}
376
377
378/*
379 * pseudo signature:
380 *
381 * int API_dev_read(
382 * struct device_info *di,
383 * void *buf,
384 * size_t *len,
385 * unsigned long *start
386 * size_t *act_len
387 * )
388 *
389 * buf: ptr to buffer where to put the read data
390 *
391 * len: ptr to length to be read
392 * - network: len of packet to read (in bytes)
393 * - storage: # of blocks to read (can vary in size depending on define)
394 *
395 * start: ptr to start block (only used for storage devices, ignored for
396 * network)
397 *
398 * act_len: ptr to where to put the len actually read
399 */
400static int API_dev_read(va_list ap)
401{
402 struct device_info *di;
403 void *buf;
404 lbasize_t *len_stor, *act_len_stor;
405 lbastart_t *start;
406 int *len_net, *act_len_net;
407
408 /* 1. arg is ptr to the device_info struct */
Stanislav Galabov78757d52016-02-17 15:23:31 +0200409 di = (struct device_info *)va_arg(ap, uintptr_t);
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100410 if (di == NULL)
411 return API_EINVAL;
412
413 /* XXX should we check if device is open? i.e. the ->state ? */
414
415 if (di->cookie == NULL)
416 return API_ENODEV;
417
418 /* 2. arg is ptr to buffer from where to put the read data */
Stanislav Galabov78757d52016-02-17 15:23:31 +0200419 buf = (void *)va_arg(ap, uintptr_t);
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100420 if (buf == NULL)
421 return API_EINVAL;
422
423 if (di->type & DEV_TYP_STOR) {
424 /* 3. arg - ptr to var with # of blocks to read */
Stanislav Galabov78757d52016-02-17 15:23:31 +0200425 len_stor = (lbasize_t *)va_arg(ap, uintptr_t);
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100426 if (!len_stor)
427 return API_EINVAL;
428 if (*len_stor <= 0)
429 return API_EINVAL;
430
431 /* 4. arg - ptr to var with start block */
Stanislav Galabov78757d52016-02-17 15:23:31 +0200432 start = (lbastart_t *)va_arg(ap, uintptr_t);
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100433
434 /* 5. arg - ptr to var where to put the len actually read */
Stanislav Galabov78757d52016-02-17 15:23:31 +0200435 act_len_stor = (lbasize_t *)va_arg(ap, uintptr_t);
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100436 if (!act_len_stor)
437 return API_EINVAL;
438
439 *act_len_stor = dev_read_stor(di->cookie, buf, *len_stor, *start);
440
441 } else if (di->type & DEV_TYP_NET) {
442
443 /* 3. arg points to the var with length of packet to read */
Stanislav Galabov78757d52016-02-17 15:23:31 +0200444 len_net = (int *)va_arg(ap, uintptr_t);
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100445 if (!len_net)
446 return API_EINVAL;
447 if (*len_net <= 0)
448 return API_EINVAL;
449
450 /* 4. - ptr to var where to put the len actually read */
Stanislav Galabov78757d52016-02-17 15:23:31 +0200451 act_len_net = (int *)va_arg(ap, uintptr_t);
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100452 if (!act_len_net)
453 return API_EINVAL;
454
455 *act_len_net = dev_read_net(di->cookie, buf, *len_net);
456
457 } else
458 return API_ENODEV;
459
460 return 0;
461}
462
463
464/*
465 * pseudo signature:
466 *
467 * int API_env_get(const char *name, char **value)
468 *
469 * name: ptr to name of env var
470 */
471static int API_env_get(va_list ap)
472{
473 char *name, **value;
474
Stanislav Galabov78757d52016-02-17 15:23:31 +0200475 if ((name = (char *)va_arg(ap, uintptr_t)) == NULL)
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100476 return API_EINVAL;
Stanislav Galabov78757d52016-02-17 15:23:31 +0200477 if ((value = (char **)va_arg(ap, uintptr_t)) == NULL)
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100478 return API_EINVAL;
479
Simon Glass00caae62017-08-03 12:22:12 -0600480 *value = env_get(name);
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100481
482 return 0;
483}
484
485/*
486 * pseudo signature:
487 *
488 * int API_env_set(const char *name, const char *value)
489 *
490 * name: ptr to name of env var
491 *
492 * value: ptr to value to be set
493 */
494static int API_env_set(va_list ap)
495{
496 char *name, *value;
497
Stanislav Galabov78757d52016-02-17 15:23:31 +0200498 if ((name = (char *)va_arg(ap, uintptr_t)) == NULL)
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100499 return API_EINVAL;
Stanislav Galabov78757d52016-02-17 15:23:31 +0200500 if ((value = (char *)va_arg(ap, uintptr_t)) == NULL)
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100501 return API_EINVAL;
502
Simon Glass382bee52017-08-03 12:22:09 -0600503 env_set(name, value);
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100504
505 return 0;
506}
507
508/*
509 * pseudo signature:
510 *
511 * int API_env_enum(const char *last, char **next)
512 *
513 * last: ptr to name of env var found in last iteration
514 */
515static int API_env_enum(va_list ap)
516{
Emmanuel Vadot6215bd42016-12-26 18:57:56 +0100517 int i, buflen;
518 char *last, **next, *s;
Simon Glassdd2408c2019-08-02 09:44:18 -0600519 struct env_entry *match, search;
Emmanuel Vadot6215bd42016-12-26 18:57:56 +0100520 static char *var;
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100521
Stanislav Galabov78757d52016-02-17 15:23:31 +0200522 last = (char *)va_arg(ap, unsigned long);
Wolfgang Denkd3a65322008-01-10 00:55:14 +0100523
Stanislav Galabov78757d52016-02-17 15:23:31 +0200524 if ((next = (char **)va_arg(ap, uintptr_t)) == NULL)
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100525 return API_EINVAL;
526
Emmanuel Vadot6215bd42016-12-26 18:57:56 +0100527 if (last == NULL) {
528 var = NULL;
529 i = 0;
530 } else {
531 var = strdup(last);
532 s = strchr(var, '=');
533 if (s != NULL)
534 *s = 0;
535 search.key = var;
Simon Glass3f0d6802019-08-01 09:47:09 -0600536 i = hsearch_r(search, ENV_FIND, &match, &env_htab, 0);
Emmanuel Vadot6215bd42016-12-26 18:57:56 +0100537 if (i == 0) {
538 i = API_EINVAL;
539 goto done;
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100540 }
541 }
542
Emmanuel Vadot6215bd42016-12-26 18:57:56 +0100543 /* match the next entry after i */
544 i = hmatch_r("", i, &match, &env_htab);
545 if (i == 0)
546 goto done;
547 buflen = strlen(match->key) + strlen(match->data) + 2;
548 var = realloc(var, buflen);
549 snprintf(var, buflen, "%s=%s", match->key, match->data);
550 *next = var;
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100551 return 0;
Emmanuel Vadot6215bd42016-12-26 18:57:56 +0100552
553done:
554 free(var);
555 var = NULL;
556 *next = NULL;
557 return i;
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100558}
559
Che-Liang Chioua2a57292011-10-20 23:04:22 +0000560/*
561 * pseudo signature:
562 *
563 * int API_display_get_info(int type, struct display_info *di)
564 */
565static int API_display_get_info(va_list ap)
566{
567 int type;
568 struct display_info *di;
569
570 type = va_arg(ap, int);
571 di = va_arg(ap, struct display_info *);
572
573 return display_get_info(type, di);
574}
575
576/*
577 * pseudo signature:
578 *
579 * int API_display_draw_bitmap(ulong bitmap, int x, int y)
580 */
581static int API_display_draw_bitmap(va_list ap)
582{
583 ulong bitmap;
584 int x, y;
585
586 bitmap = va_arg(ap, ulong);
587 x = va_arg(ap, int);
588 y = va_arg(ap, int);
589
590 return display_draw_bitmap(bitmap, x, y);
591}
592
593/*
594 * pseudo signature:
595 *
596 * void API_display_clear(void)
597 */
598static int API_display_clear(va_list ap)
599{
600 display_clear();
601 return 0;
602}
603
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100604static cfp_t calls_table[API_MAXCALL] = { NULL, };
605
606/*
607 * The main syscall entry point - this is not reentrant, only one call is
608 * serviced until finished.
609 *
610 * e.g. syscall(1, int *, u_int32_t, u_int32_t, u_int32_t, u_int32_t);
Wolfgang Denkd3a65322008-01-10 00:55:14 +0100611 *
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100612 * call: syscall number
613 *
614 * retval: points to the return value placeholder, this is the place the
615 * syscall puts its return value, if NULL the caller does not
616 * expect a return value
617 *
618 * ... syscall arguments (variable number)
619 *
620 * returns: 0 if the call not found, 1 if serviced
621 */
622int syscall(int call, int *retval, ...)
623{
624 va_list ap;
625 int rv;
626
Jean-Christophe PLAGNIOL-VILLARD20e5ed12008-05-11 23:13:57 +0200627 if (call < 0 || call >= calls_no) {
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100628 debugf("invalid call #%d\n", call);
629 return 0;
630 }
631
632 if (calls_table[call] == NULL) {
633 debugf("syscall #%d does not have a handler\n", call);
634 return 0;
635 }
636
637 va_start(ap, retval);
638 rv = calls_table[call](ap);
639 if (retval != NULL)
640 *retval = rv;
641
642 return 1;
643}
644
Ovidiu Panaitce41e732020-11-28 10:43:16 +0200645int api_init(void)
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100646{
xypron.glpk@gmx.de5cc9e6b2017-07-30 19:54:37 +0200647 struct api_signature *sig;
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100648
649 /* TODO put this into linker set one day... */
650 calls_table[API_RSVD] = NULL;
651 calls_table[API_GETC] = &API_getc;
652 calls_table[API_PUTC] = &API_putc;
653 calls_table[API_TSTC] = &API_tstc;
654 calls_table[API_PUTS] = &API_puts;
655 calls_table[API_RESET] = &API_reset;
656 calls_table[API_GET_SYS_INFO] = &API_get_sys_info;
657 calls_table[API_UDELAY] = &API_udelay;
658 calls_table[API_GET_TIMER] = &API_get_timer;
659 calls_table[API_DEV_ENUM] = &API_dev_enum;
660 calls_table[API_DEV_OPEN] = &API_dev_open;
661 calls_table[API_DEV_CLOSE] = &API_dev_close;
662 calls_table[API_DEV_READ] = &API_dev_read;
663 calls_table[API_DEV_WRITE] = &API_dev_write;
664 calls_table[API_ENV_GET] = &API_env_get;
665 calls_table[API_ENV_SET] = &API_env_set;
666 calls_table[API_ENV_ENUM] = &API_env_enum;
Che-Liang Chioua2a57292011-10-20 23:04:22 +0000667 calls_table[API_DISPLAY_GET_INFO] = &API_display_get_info;
668 calls_table[API_DISPLAY_DRAW_BITMAP] = &API_display_draw_bitmap;
669 calls_table[API_DISPLAY_CLEAR] = &API_display_clear;
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100670 calls_no = API_MAXCALL;
671
672 debugf("API initialized with %d calls\n", calls_no);
673
674 dev_stor_init();
675
676 /*
677 * Produce the signature so the API consumers can find it
678 */
679 sig = malloc(sizeof(struct api_signature));
680 if (sig == NULL) {
681 printf("API: could not allocate memory for the signature!\n");
Ovidiu Panaitce41e732020-11-28 10:43:16 +0200682 return -ENOMEM;
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100683 }
684
Simon Glass018f5302017-08-03 12:22:10 -0600685 env_set_hex("api_address", (unsigned long)sig);
Stanislav Galabov78757d52016-02-17 15:23:31 +0200686 debugf("API sig @ 0x%lX\n", (unsigned long)sig);
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100687 memcpy(sig->magic, API_SIG_MAGIC, 8);
688 sig->version = API_SIG_VERSION;
689 sig->syscall = &syscall;
690 sig->checksum = 0;
691 sig->checksum = crc32(0, (unsigned char *)sig,
692 sizeof(struct api_signature));
Stanislav Galabov78757d52016-02-17 15:23:31 +0200693 debugf("syscall entry: 0x%lX\n", (unsigned long)sig->syscall);
Ovidiu Panaitce41e732020-11-28 10:43:16 +0200694
695 return 0;
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100696}
697
698void platform_set_mr(struct sys_info *si, unsigned long start, unsigned long size,
699 int flags)
700{
701 int i;
702
703 if (!si->mr || !size || (flags == 0))
704 return;
Wolfgang Denkd3a65322008-01-10 00:55:14 +0100705
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100706 /* find free slot */
707 for (i = 0; i < si->mr_no; i++)
708 if (si->mr[i].flags == 0) {
709 /* insert new mem region */
710 si->mr[i].start = start;
711 si->mr[i].size = size;
712 si->mr[i].flags = flags;
713 return;
714 }
715}