1
2
3
4
5
6
7
8#include <config.h>
9#include <command.h>
10#include <env.h>
11#include <malloc.h>
12#include <time.h>
13#include <env_internal.h>
14#include <vsprintf.h>
15#include <linux/delay.h>
16#include <linux/errno.h>
17#include <linux/types.h>
18#include <api_public.h>
19#include <u-boot/crc.h>
20
21#include "api_private.h"
22
23#define DEBUG
24#undef DEBUG
25
26
27
28
29
30
31
32
33
34
35
36
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
52
53
54
55static int API_getc(va_list ap)
56{
57 int *c;
58
59 if ((c = (int *)va_arg(ap, uintptr_t)) == NULL)
60 return API_EINVAL;
61
62 *c = getchar();
63 return 0;
64}
65
66
67
68
69
70
71static int API_tstc(va_list ap)
72{
73 int *t;
74
75 if ((t = (int *)va_arg(ap, uintptr_t)) == NULL)
76 return API_EINVAL;
77
78 *t = tstc();
79 return 0;
80}
81
82
83
84
85
86
87static int API_putc(va_list ap)
88{
89 char *c;
90
91 if ((c = (char *)va_arg(ap, uintptr_t)) == NULL)
92 return API_EINVAL;
93
94 putc(*c);
95 return 0;
96}
97
98
99
100
101
102
103static int API_puts(va_list ap)
104{
105 char *s;
106
107 if ((s = (char *)va_arg(ap, uintptr_t)) == NULL)
108 return API_EINVAL;
109
110 puts(s);
111 return 0;
112}
113
114
115
116
117
118
119static int API_reset(va_list ap)
120{
121 do_reset(NULL, 0, 0, NULL);
122
123
124 return 0;
125}
126
127
128
129
130
131
132
133
134
135static int API_get_sys_info(va_list ap)
136{
137 struct sys_info *si;
138
139 si = (struct sys_info *)va_arg(ap, uintptr_t);
140 if (si == NULL)
141 return API_ENOMEM;
142
143 return (platform_sys_info(si)) ? 0 : API_ENODEV;
144}
145
146
147
148
149
150
151static int API_udelay(va_list ap)
152{
153 unsigned long *d;
154
155 if ((d = (unsigned long *)va_arg(ap, unsigned long)) == NULL)
156 return API_EINVAL;
157
158 udelay(*d);
159 return 0;
160}
161
162
163
164
165
166
167static int API_get_timer(va_list ap)
168{
169 unsigned long *base, *cur;
170
171 cur = (unsigned long *)va_arg(ap, unsigned long);
172 if (cur == NULL)
173 return API_EINVAL;
174
175 base = (unsigned long *)va_arg(ap, unsigned long);
176 if (base == NULL)
177 return API_EINVAL;
178
179 *cur = get_timer(*base);
180 return 0;
181}
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200static int API_dev_enum(va_list ap)
201{
202 struct device_info *di;
203
204
205 di = (struct device_info *)va_arg(ap, uintptr_t);
206 if (di == NULL)
207 return API_EINVAL;
208
209 if (di->cookie == NULL) {
210
211 dev_enum_reset();
212 debugf("RESTART ENUM\n");
213
214
215 if (dev_enum_net(di))
216 return 0;
217 }
218
219
220
221
222
223
224
225 if (!dev_enum_storage(di))
226
227 di->cookie = NULL;
228
229 return 0;
230}
231
232static int API_dev_open(va_list ap)
233{
234 struct device_info *di;
235 int err = 0;
236
237
238 di = (struct device_info *)va_arg(ap, uintptr_t);
239 if (di == NULL)
240 return API_EINVAL;
241
242
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
263static int API_dev_close(va_list ap)
264{
265 struct device_info *di;
266 int err = 0;
267
268
269 di = (struct device_info *)va_arg(ap, uintptr_t);
270 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
287
288
289 err = API_ENODEV;
290
291 if (!err)
292 di->state = DEV_STA_CLOSED;
293
294 return err;
295}
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316static int API_dev_write(va_list ap)
317{
318 struct device_info *di;
319 void *buf;
320 lbasize_t *len_stor, act_len_stor;
321 lbastart_t *start;
322 int *len_net;
323 int err = 0;
324
325
326 di = (struct device_info *)va_arg(ap, uintptr_t);
327 if (di == NULL)
328 return API_EINVAL;
329
330
331
332 if (di->cookie == NULL)
333 return API_ENODEV;
334
335
336 buf = (void *)va_arg(ap, uintptr_t);
337 if (buf == NULL)
338 return API_EINVAL;
339
340 if (di->type & DEV_TYP_STOR) {
341
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;
347
348
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
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);
368
369 } else
370 err = API_ENODEV;
371
372 return err;
373}
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
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
406 di = (struct device_info *)va_arg(ap, uintptr_t);
407 if (di == NULL)
408 return API_EINVAL;
409
410
411
412 if (di->cookie == NULL)
413 return API_ENODEV;
414
415
416 buf = (void *)va_arg(ap, uintptr_t);
417 if (buf == NULL)
418 return API_EINVAL;
419
420 if (di->type & DEV_TYP_STOR) {
421
422 len_stor = (lbasize_t *)va_arg(ap, uintptr_t);
423 if (!len_stor)
424 return API_EINVAL;
425 if (*len_stor <= 0)
426 return API_EINVAL;
427
428
429 start = (lbastart_t *)va_arg(ap, uintptr_t);
430
431
432 act_len_stor = (lbasize_t *)va_arg(ap, uintptr_t);
433 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
441 len_net = (int *)va_arg(ap, uintptr_t);
442 if (!len_net)
443 return API_EINVAL;
444 if (*len_net <= 0)
445 return API_EINVAL;
446
447
448 act_len_net = (int *)va_arg(ap, uintptr_t);
449 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
460
461
462
463
464
465
466
467static int API_env_get(va_list ap)
468{
469 char *name, **value;
470
471 if ((name = (char *)va_arg(ap, uintptr_t)) == NULL)
472 return API_EINVAL;
473 if ((value = (char **)va_arg(ap, uintptr_t)) == NULL)
474 return API_EINVAL;
475
476 *value = env_get(name);
477
478 return 0;
479}
480
481
482
483
484
485
486
487
488
489
490static int API_env_set(va_list ap)
491{
492 char *name, *value;
493
494 if ((name = (char *)va_arg(ap, uintptr_t)) == NULL)
495 return API_EINVAL;
496 if ((value = (char *)va_arg(ap, uintptr_t)) == NULL)
497 return API_EINVAL;
498
499 env_set(name, value);
500
501 return 0;
502}
503
504
505
506
507
508
509
510
511static int API_env_enum(va_list ap)
512{
513 int i, buflen;
514 char *last, **next, *s;
515 struct env_entry *match, search;
516 static char *var;
517
518 last = (char *)va_arg(ap, unsigned long);
519
520 if ((next = (char **)va_arg(ap, uintptr_t)) == NULL)
521 return API_EINVAL;
522
523 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;
532 i = hsearch_r(search, ENV_FIND, &match, &env_htab, 0);
533 if (i == 0) {
534 i = API_EINVAL;
535 goto done;
536 }
537 }
538
539
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;
547 return 0;
548
549done:
550 free(var);
551 var = NULL;
552 *next = NULL;
553 return i;
554}
555
556
557
558
559
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
574
575
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
591
592
593
594static int API_display_clear(va_list ap)
595{
596 display_clear();
597 return 0;
598}
599
600static cfp_t calls_table[API_MAXCALL] = { NULL, };
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618int syscall(int call, int *retval, ...)
619{
620 va_list ap;
621 int rv;
622
623 if (call < 0 || call >= calls_no) {
624 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
641int api_init(void)
642{
643 struct api_signature *sig;
644
645
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;
663 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;
666 calls_no = API_MAXCALL;
667
668 debugf("API initialized with %d calls\n", calls_no);
669
670 dev_stor_init();
671
672
673
674
675 sig = malloc(sizeof(struct api_signature));
676 if (sig == NULL) {
677 printf("API: could not allocate memory for the signature!\n");
678 return -ENOMEM;
679 }
680
681 env_set_hex("api_address", (unsigned long)sig);
682 debugf("API sig @ 0x%lX\n", (unsigned long)sig);
683 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));
689 debugf("syscall entry: 0x%lX\n", (unsigned long)sig->syscall);
690
691 return 0;
692}
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;
701
702
703 for (i = 0; i < si->mr_no; i++)
704 if (si->mr[i].flags == 0) {
705
706 si->mr[i].start = start;
707 si->mr[i].size = size;
708 si->mr[i].flags = flags;
709 return;
710 }
711}
712