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