1 // SPDX-License-Identifier: GPL-2.0+
3 * (C) Copyright 2007 Semihalf
13 #include <env_internal.h>
14 #include <linux/types.h>
15 #include <api_public.h>
16 #include <u-boot/crc.h>
18 #include "api_private.h"
23 /*****************************************************************************
25 * This is the API core.
27 * API_ functions are part of U-Boot code and constitute the lowest level
30 * - they know what values they need as arguments
31 * - their direct return value pertains to the API_ "shell" itself (0 on
32 * success, some error code otherwise)
33 * - if the call returns a value it is buried within arguments
35 ****************************************************************************/
38 #define debugf(fmt, args...) do { printf("%s(): ", __func__); printf(fmt, ##args); } while (0)
40 #define debugf(fmt, args...)
43 typedef int (*cfp_t)(va_list argp);
50 * int API_getc(int *c)
52 static int API_getc(va_list ap)
56 if ((c = (int *)va_arg(ap, uintptr_t)) == NULL)
66 * int API_tstc(int *c)
68 static int API_tstc(va_list ap)
72 if ((t = (int *)va_arg(ap, uintptr_t)) == NULL)
82 * int API_putc(char *ch)
84 static int API_putc(va_list ap)
88 if ((c = (char *)va_arg(ap, uintptr_t)) == NULL)
98 * int API_puts(char **s)
100 static int API_puts(va_list ap)
104 if ((s = (char *)va_arg(ap, uintptr_t)) == NULL)
114 * int API_reset(void)
116 static int API_reset(va_list ap)
118 do_reset(NULL, 0, 0, NULL);
127 * int API_get_sys_info(struct sys_info *si)
129 * fill out the sys_info struct containing selected parameters about the
132 static int API_get_sys_info(va_list ap)
136 si = (struct sys_info *)va_arg(ap, uintptr_t);
140 return (platform_sys_info(si)) ? 0 : API_ENODEV;
146 * int API_udelay(unsigned long *udelay)
148 static int API_udelay(va_list ap)
152 if ((d = (unsigned long *)va_arg(ap, unsigned long)) == NULL)
162 * int API_get_timer(unsigned long *current, unsigned long *base)
164 static int API_get_timer(va_list ap)
166 unsigned long *base, *cur;
168 cur = (unsigned long *)va_arg(ap, unsigned long);
172 base = (unsigned long *)va_arg(ap, unsigned long);
176 *cur = get_timer(*base);
181 /*****************************************************************************
185 * int API_dev_enum(struct device_info *)
188 * cookies uniqely identify the previously enumerated device instance and
189 * provide a hint for what to inspect in current enum iteration:
191 * - net: ð_device struct address from list pointed to by eth_devices
193 * - storage: struct blk_desc struct address from &ide_dev_desc[n],
194 * &scsi_dev_desc[n] and similar tables
196 ****************************************************************************/
198 static int API_dev_enum(va_list ap)
200 struct device_info *di;
202 /* arg is ptr to the device_info struct we are going to fill out */
203 di = (struct device_info *)va_arg(ap, uintptr_t);
207 if (di->cookie == NULL) {
208 /* start over - clean up enumeration */
209 dev_enum_reset(); /* XXX shouldn't the name contain 'stor'? */
210 debugf("RESTART ENUM\n");
212 /* net device enumeration first */
213 if (dev_enum_net(di))
218 * The hidden assumption is there can only be one active network
219 * device and it is identified upon enumeration (re)start, so there's
220 * no point in trying to find network devices in other cases than the
221 * (re)start and hence the 'next' device can only be storage
223 if (!dev_enum_storage(di))
224 /* make sure we mark there are no more devices */
231 static int API_dev_open(va_list ap)
233 struct device_info *di;
236 /* arg is ptr to the device_info struct */
237 di = (struct device_info *)va_arg(ap, uintptr_t);
241 /* Allow only one consumer of the device at a time */
242 if (di->state == DEV_STA_OPEN)
245 if (di->cookie == NULL)
248 if (di->type & DEV_TYP_STOR)
249 err = dev_open_stor(di->cookie);
251 else if (di->type & DEV_TYP_NET)
252 err = dev_open_net(di->cookie);
257 di->state = DEV_STA_OPEN;
263 static int API_dev_close(va_list ap)
265 struct device_info *di;
268 /* arg is ptr to the device_info struct */
269 di = (struct device_info *)va_arg(ap, uintptr_t);
273 if (di->state == DEV_STA_CLOSED)
276 if (di->cookie == NULL)
279 if (di->type & DEV_TYP_STOR)
280 err = dev_close_stor(di->cookie);
282 else if (di->type & DEV_TYP_NET)
283 err = dev_close_net(di->cookie);
286 * In case of unknown device we cannot change its state, so
287 * only return error code
292 di->state = DEV_STA_CLOSED;
302 * struct device_info *di,
305 * unsigned long *start
308 * buf: ptr to buffer from where to get the data to send
310 * len: ptr to length to be read
311 * - network: len of packet to be sent (in bytes)
312 * - storage: # of blocks to write (can vary in size depending on define)
314 * start: ptr to start block (only used for storage devices, ignored for
317 static int API_dev_write(va_list ap)
319 struct device_info *di;
321 lbasize_t *len_stor, act_len_stor;
326 /* 1. arg is ptr to the device_info struct */
327 di = (struct device_info *)va_arg(ap, uintptr_t);
331 /* XXX should we check if device is open? i.e. the ->state ? */
333 if (di->cookie == NULL)
336 /* 2. arg is ptr to buffer from where to get data to write */
337 buf = (void *)va_arg(ap, uintptr_t);
341 if (di->type & DEV_TYP_STOR) {
342 /* 3. arg - ptr to var with # of blocks to write */
343 len_stor = (lbasize_t *)va_arg(ap, uintptr_t);
349 /* 4. arg - ptr to var with start block */
350 start = (lbastart_t *)va_arg(ap, uintptr_t);
352 act_len_stor = dev_write_stor(di->cookie, buf, *len_stor, *start);
353 if (act_len_stor != *len_stor) {
354 debugf("write @ %llu: done %llu out of %llu blocks",
355 (uint64_t)blk, (uint64_t)act_len_stor,
360 } else if (di->type & DEV_TYP_NET) {
361 /* 3. arg points to the var with length of packet to write */
362 len_net = (int *)va_arg(ap, uintptr_t);
368 err = dev_write_net(di->cookie, buf, *len_net);
381 * struct device_info *di,
384 * unsigned long *start
388 * buf: ptr to buffer where to put the read data
390 * len: ptr to length to be read
391 * - network: len of packet to read (in bytes)
392 * - storage: # of blocks to read (can vary in size depending on define)
394 * start: ptr to start block (only used for storage devices, ignored for
397 * act_len: ptr to where to put the len actually read
399 static int API_dev_read(va_list ap)
401 struct device_info *di;
403 lbasize_t *len_stor, *act_len_stor;
405 int *len_net, *act_len_net;
407 /* 1. arg is ptr to the device_info struct */
408 di = (struct device_info *)va_arg(ap, uintptr_t);
412 /* XXX should we check if device is open? i.e. the ->state ? */
414 if (di->cookie == NULL)
417 /* 2. arg is ptr to buffer from where to put the read data */
418 buf = (void *)va_arg(ap, uintptr_t);
422 if (di->type & DEV_TYP_STOR) {
423 /* 3. arg - ptr to var with # of blocks to read */
424 len_stor = (lbasize_t *)va_arg(ap, uintptr_t);
430 /* 4. arg - ptr to var with start block */
431 start = (lbastart_t *)va_arg(ap, uintptr_t);
433 /* 5. arg - ptr to var where to put the len actually read */
434 act_len_stor = (lbasize_t *)va_arg(ap, uintptr_t);
438 *act_len_stor = dev_read_stor(di->cookie, buf, *len_stor, *start);
440 } else if (di->type & DEV_TYP_NET) {
442 /* 3. arg points to the var with length of packet to read */
443 len_net = (int *)va_arg(ap, uintptr_t);
449 /* 4. - ptr to var where to put the len actually read */
450 act_len_net = (int *)va_arg(ap, uintptr_t);
454 *act_len_net = dev_read_net(di->cookie, buf, *len_net);
466 * int API_env_get(const char *name, char **value)
468 * name: ptr to name of env var
470 static int API_env_get(va_list ap)
474 if ((name = (char *)va_arg(ap, uintptr_t)) == NULL)
476 if ((value = (char **)va_arg(ap, uintptr_t)) == NULL)
479 *value = env_get(name);
487 * int API_env_set(const char *name, const char *value)
489 * name: ptr to name of env var
491 * value: ptr to value to be set
493 static int API_env_set(va_list ap)
497 if ((name = (char *)va_arg(ap, uintptr_t)) == NULL)
499 if ((value = (char *)va_arg(ap, uintptr_t)) == NULL)
502 env_set(name, value);
510 * int API_env_enum(const char *last, char **next)
512 * last: ptr to name of env var found in last iteration
514 static int API_env_enum(va_list ap)
517 char *last, **next, *s;
518 struct env_entry *match, search;
521 last = (char *)va_arg(ap, unsigned long);
523 if ((next = (char **)va_arg(ap, uintptr_t)) == NULL)
531 s = strchr(var, '=');
535 i = hsearch_r(search, ENV_FIND, &match, &env_htab, 0);
542 /* match the next entry after i */
543 i = hmatch_r("", i, &match, &env_htab);
546 buflen = strlen(match->key) + strlen(match->data) + 2;
547 var = realloc(var, buflen);
548 snprintf(var, buflen, "%s=%s", match->key, match->data);
562 * int API_display_get_info(int type, struct display_info *di)
564 static int API_display_get_info(va_list ap)
567 struct display_info *di;
569 type = va_arg(ap, int);
570 di = va_arg(ap, struct display_info *);
572 return display_get_info(type, di);
578 * int API_display_draw_bitmap(ulong bitmap, int x, int y)
580 static int API_display_draw_bitmap(va_list ap)
585 bitmap = va_arg(ap, ulong);
589 return display_draw_bitmap(bitmap, x, y);
595 * void API_display_clear(void)
597 static int API_display_clear(va_list ap)
603 static cfp_t calls_table[API_MAXCALL] = { NULL, };
606 * The main syscall entry point - this is not reentrant, only one call is
607 * serviced until finished.
609 * e.g. syscall(1, int *, u_int32_t, u_int32_t, u_int32_t, u_int32_t);
611 * call: syscall number
613 * retval: points to the return value placeholder, this is the place the
614 * syscall puts its return value, if NULL the caller does not
615 * expect a return value
617 * ... syscall arguments (variable number)
619 * returns: 0 if the call not found, 1 if serviced
621 int syscall(int call, int *retval, ...)
626 if (call < 0 || call >= calls_no) {
627 debugf("invalid call #%d\n", call);
631 if (calls_table[call] == NULL) {
632 debugf("syscall #%d does not have a handler\n", call);
636 va_start(ap, retval);
637 rv = calls_table[call](ap);
646 struct api_signature *sig;
648 /* TODO put this into linker set one day... */
649 calls_table[API_RSVD] = NULL;
650 calls_table[API_GETC] = &API_getc;
651 calls_table[API_PUTC] = &API_putc;
652 calls_table[API_TSTC] = &API_tstc;
653 calls_table[API_PUTS] = &API_puts;
654 calls_table[API_RESET] = &API_reset;
655 calls_table[API_GET_SYS_INFO] = &API_get_sys_info;
656 calls_table[API_UDELAY] = &API_udelay;
657 calls_table[API_GET_TIMER] = &API_get_timer;
658 calls_table[API_DEV_ENUM] = &API_dev_enum;
659 calls_table[API_DEV_OPEN] = &API_dev_open;
660 calls_table[API_DEV_CLOSE] = &API_dev_close;
661 calls_table[API_DEV_READ] = &API_dev_read;
662 calls_table[API_DEV_WRITE] = &API_dev_write;
663 calls_table[API_ENV_GET] = &API_env_get;
664 calls_table[API_ENV_SET] = &API_env_set;
665 calls_table[API_ENV_ENUM] = &API_env_enum;
666 calls_table[API_DISPLAY_GET_INFO] = &API_display_get_info;
667 calls_table[API_DISPLAY_DRAW_BITMAP] = &API_display_draw_bitmap;
668 calls_table[API_DISPLAY_CLEAR] = &API_display_clear;
669 calls_no = API_MAXCALL;
671 debugf("API initialized with %d calls\n", calls_no);
676 * Produce the signature so the API consumers can find it
678 sig = malloc(sizeof(struct api_signature));
680 printf("API: could not allocate memory for the signature!\n");
684 env_set_hex("api_address", (unsigned long)sig);
685 debugf("API sig @ 0x%lX\n", (unsigned long)sig);
686 memcpy(sig->magic, API_SIG_MAGIC, 8);
687 sig->version = API_SIG_VERSION;
688 sig->syscall = &syscall;
690 sig->checksum = crc32(0, (unsigned char *)sig,
691 sizeof(struct api_signature));
692 debugf("syscall entry: 0x%lX\n", (unsigned long)sig->syscall);
695 void platform_set_mr(struct sys_info *si, unsigned long start, unsigned long size,
700 if (!si->mr || !size || (flags == 0))
704 for (i = 0; i < si->mr_no; i++)
705 if (si->mr[i].flags == 0) {
706 /* insert new mem region */
707 si->mr[i].start = start;
708 si->mr[i].size = size;
709 si->mr[i].flags = flags;