blob: 075d307ae2611090fa4d0cb5ae71c019db4b5f55 [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/*
Rafal Jaworowski923aa482009-01-23 13:27:18 +01003 * (C) Copyright 2007-2008 Semihalf, Rafal Jaworowski <raj@semihalf.com>
Rafal Jaworowski500856e2008-01-09 19:39:36 +01004 */
5
6#include <common.h>
Simon Glassb9ca02c2019-08-01 09:46:45 -06007#include <env.h>
Rafal Jaworowski500856e2008-01-09 19:39:36 +01008#include <linux/types.h>
9#include <api_public.h>
Simon Glass3db71102019-11-14 12:57:16 -070010#include <u-boot/crc.h>
Rafal Jaworowski500856e2008-01-09 19:39:36 +010011
12#include "glue.h"
13
14static int valid_sig(struct api_signature *sig)
15{
16 uint32_t checksum;
17 struct api_signature s;
18
19 if (sig == NULL)
20 return 0;
21 /*
22 * Clear the checksum field (in the local copy) so as to calculate the
23 * CRC with the same initial contents as at the time when the sig was
24 * produced
25 */
26 s = *sig;
27 s.checksum = 0;
28
29 checksum = crc32(0, (unsigned char *)&s, sizeof(struct api_signature));
30
31 if (checksum != sig->checksum)
32 return 0;
33
34 return 1;
35}
36
37/*
38 * Searches for the U-Boot API signature
39 *
40 * returns 1/0 depending on found/not found result
41 */
Rafal Jaworowski923aa482009-01-23 13:27:18 +010042int api_search_sig(struct api_signature **sig)
43{
Rafal Jaworowski500856e2008-01-09 19:39:36 +010044 unsigned char *sp;
Rafal Jaworowskib84d7d82009-01-23 13:27:15 +010045 uint32_t search_start = 0;
46 uint32_t search_end = 0;
Rafal Jaworowski500856e2008-01-09 19:39:36 +010047
48 if (sig == NULL)
49 return 0;
50
Rafal Jaworowskib84d7d82009-01-23 13:27:15 +010051 if (search_hint == 0)
52 search_hint = 255 * 1024 * 1024;
Rafal Jaworowski500856e2008-01-09 19:39:36 +010053
Rafal Jaworowskib84d7d82009-01-23 13:27:15 +010054 search_start = search_hint & ~0x000fffff;
55 search_end = search_start + API_SEARCH_LEN - API_SIG_MAGLEN;
56
57 sp = (unsigned char *)search_start;
58 while ((sp + API_SIG_MAGLEN) < (unsigned char *)search_end) {
Rafal Jaworowski500856e2008-01-09 19:39:36 +010059 if (!memcmp(sp, API_SIG_MAGIC, API_SIG_MAGLEN)) {
60 *sig = (struct api_signature *)sp;
61 if (valid_sig(*sig))
62 return 1;
63 }
64 sp += API_SIG_MAGLEN;
65 }
66
67 *sig = NULL;
68 return 0;
69}
70
71/****************************************
72 *
73 * console
74 *
75 ****************************************/
76
77int ub_getc(void)
78{
79 int c;
80
Stanislav Galabov78757d52016-02-17 15:23:31 +020081 if (!syscall(API_GETC, NULL, &c))
Rafal Jaworowski500856e2008-01-09 19:39:36 +010082 return -1;
83
84 return c;
85}
86
87int ub_tstc(void)
88{
89 int t;
90
Stanislav Galabov78757d52016-02-17 15:23:31 +020091 if (!syscall(API_TSTC, NULL, &t))
Rafal Jaworowski500856e2008-01-09 19:39:36 +010092 return -1;
93
94 return t;
95}
96
97void ub_putc(char c)
98{
Stanislav Galabov78757d52016-02-17 15:23:31 +020099 syscall(API_PUTC, NULL, &c);
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100100}
101
102void ub_puts(const char *s)
103{
Stanislav Galabov78757d52016-02-17 15:23:31 +0200104 syscall(API_PUTS, NULL, s);
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100105}
106
107/****************************************
108 *
109 * system
110 *
111 ****************************************/
112
113void ub_reset(void)
114{
115 syscall(API_RESET, NULL);
116}
117
Rafal Jaworowski923aa482009-01-23 13:27:18 +0100118static struct mem_region mr[UB_MAX_MR];
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100119static struct sys_info si;
120
121struct sys_info * ub_get_sys_info(void)
122{
123 int err = 0;
124
125 memset(&si, 0, sizeof(struct sys_info));
126 si.mr = mr;
Rafal Jaworowski923aa482009-01-23 13:27:18 +0100127 si.mr_no = UB_MAX_MR;
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100128 memset(&mr, 0, sizeof(mr));
129
Stanislav Galabov78757d52016-02-17 15:23:31 +0200130 if (!syscall(API_GET_SYS_INFO, &err, &si))
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100131 return NULL;
132
133 return ((err) ? NULL : &si);
134}
135
136/****************************************
137 *
138 * timing
139 *
140 ****************************************/
Wolfgang Denkd3a65322008-01-10 00:55:14 +0100141
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100142void ub_udelay(unsigned long usec)
143{
144 syscall(API_UDELAY, NULL, &usec);
145}
146
147unsigned long ub_get_timer(unsigned long base)
148{
149 unsigned long cur;
150
151 if (!syscall(API_GET_TIMER, NULL, &cur, &base))
152 return 0;
153
154 return cur;
155}
156
157
158/****************************************************************************
159 *
160 * devices
161 *
Rafal Jaworowski923aa482009-01-23 13:27:18 +0100162 * Devices are identified by handles: numbers 0, 1, 2, ..., UB_MAX_DEV-1
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100163 *
164 ***************************************************************************/
165
Rafal Jaworowski923aa482009-01-23 13:27:18 +0100166static struct device_info devices[UB_MAX_DEV];
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100167
168struct device_info * ub_dev_get(int i)
169{
Rafal Jaworowski923aa482009-01-23 13:27:18 +0100170 return ((i < 0 || i >= UB_MAX_DEV) ? NULL : &devices[i]);
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100171}
172
173/*
174 * Enumerates the devices: fills out device_info elements in the devices[]
175 * array.
176 *
177 * returns: number of devices found
178 */
179int ub_dev_enum(void)
180{
181 struct device_info *di;
182 int n = 0;
183
Rafal Jaworowski923aa482009-01-23 13:27:18 +0100184 memset(&devices, 0, sizeof(struct device_info) * UB_MAX_DEV);
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100185 di = &devices[0];
186
187 if (!syscall(API_DEV_ENUM, NULL, di))
188 return 0;
189
190 while (di->cookie != NULL) {
191
Rafal Jaworowski923aa482009-01-23 13:27:18 +0100192 if (++n >= UB_MAX_DEV)
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100193 break;
194
195 /* take another device_info */
196 di++;
197
198 /* pass on the previous cookie */
199 di->cookie = devices[n - 1].cookie;
200
201 if (!syscall(API_DEV_ENUM, NULL, di))
202 return 0;
203 }
204
205 return n;
206}
207
208/*
209 * handle: 0-based id of the device
210 *
211 * returns: 0 when OK, err otherwise
212 */
213int ub_dev_open(int handle)
214{
215 struct device_info *di;
216 int err = 0;
217
Rafal Jaworowski923aa482009-01-23 13:27:18 +0100218 if (handle < 0 || handle >= UB_MAX_DEV)
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100219 return API_EINVAL;
220
221 di = &devices[handle];
222
223 if (!syscall(API_DEV_OPEN, &err, di))
224 return -1;
225
226 return err;
227}
228
229int ub_dev_close(int handle)
230{
231 struct device_info *di;
232
Rafal Jaworowski923aa482009-01-23 13:27:18 +0100233 if (handle < 0 || handle >= UB_MAX_DEV)
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100234 return API_EINVAL;
235
236 di = &devices[handle];
237 if (!syscall(API_DEV_CLOSE, NULL, di))
238 return -1;
239
240 return 0;
241}
242
243/*
244 *
245 * Validates device for read/write, it has to:
246 *
247 * - have sane handle
248 * - be opened
249 *
250 * returns: 0/1 accordingly
251 */
252static int dev_valid(int handle)
253{
Rafal Jaworowski923aa482009-01-23 13:27:18 +0100254 if (handle < 0 || handle >= UB_MAX_DEV)
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100255 return 0;
256
257 if (devices[handle].state != DEV_STA_OPEN)
258 return 0;
259
260 return 1;
261}
262
263static int dev_stor_valid(int handle)
264{
265 if (!dev_valid(handle))
266 return 0;
267
268 if (!(devices[handle].type & DEV_TYP_STOR))
269 return 0;
270
271 return 1;
272}
273
Rafal Jaworowski923aa482009-01-23 13:27:18 +0100274int ub_dev_read(int handle, void *buf, lbasize_t len, lbastart_t start,
275 lbasize_t *rlen)
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100276{
277 struct device_info *di;
278 lbasize_t act_len;
279 int err = 0;
280
281 if (!dev_stor_valid(handle))
282 return API_ENODEV;
283
284 di = &devices[handle];
285 if (!syscall(API_DEV_READ, &err, di, buf, &len, &start, &act_len))
Rafal Jaworowski923aa482009-01-23 13:27:18 +0100286 return API_ESYSC;
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100287
Rafal Jaworowski923aa482009-01-23 13:27:18 +0100288 if (!err && rlen)
289 *rlen = act_len;
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100290
Rafal Jaworowski923aa482009-01-23 13:27:18 +0100291 return err;
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100292}
293
294static int dev_net_valid(int handle)
295{
296 if (!dev_valid(handle))
297 return 0;
298
299 if (devices[handle].type != DEV_TYP_NET)
300 return 0;
301
302 return 1;
303}
304
Rafal Jaworowski923aa482009-01-23 13:27:18 +0100305int ub_dev_recv(int handle, void *buf, int len, int *rlen)
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100306{
307 struct device_info *di;
308 int err = 0, act_len;
309
310 if (!dev_net_valid(handle))
311 return API_ENODEV;
312
313 di = &devices[handle];
314 if (!syscall(API_DEV_READ, &err, di, buf, &len, &act_len))
Rafal Jaworowski923aa482009-01-23 13:27:18 +0100315 return API_ESYSC;
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100316
Rafal Jaworowski923aa482009-01-23 13:27:18 +0100317 if (!err && rlen)
318 *rlen = act_len;
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100319
Rafal Jaworowski923aa482009-01-23 13:27:18 +0100320 return (err);
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100321}
322
323int ub_dev_send(int handle, void *buf, int len)
324{
325 struct device_info *di;
326 int err = 0;
327
328 if (!dev_net_valid(handle))
329 return API_ENODEV;
330
331 di = &devices[handle];
332 if (!syscall(API_DEV_WRITE, &err, di, buf, &len))
Rafal Jaworowski923aa482009-01-23 13:27:18 +0100333 return API_ESYSC;
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100334
335 return err;
336}
337
338/****************************************
339 *
340 * env vars
341 *
342 ****************************************/
343
344char * ub_env_get(const char *name)
345{
346 char *value;
347
Stanislav Galabov78757d52016-02-17 15:23:31 +0200348 if (!syscall(API_ENV_GET, NULL, name, &value))
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100349 return NULL;
350
351 return value;
352}
353
354void ub_env_set(const char *name, char *value)
355{
Stanislav Galabov78757d52016-02-17 15:23:31 +0200356 syscall(API_ENV_SET, NULL, name, value);
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100357}
358
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100359static char env_name[256];
360
361const char * ub_env_enum(const char *last)
362{
363 const char *env, *str;
364 int i;
365
366 env = NULL;
367
Stanislav Galabov78757d52016-02-17 15:23:31 +0200368 if (!syscall(API_ENV_ENUM, NULL, last, &env))
Rafal Jaworowski500856e2008-01-09 19:39:36 +0100369 return NULL;
370
371 if (!env)
372 /* no more env. variables to enumerate */
373 return NULL;
374
375 /* next enumerated env var */
376 memset(env_name, 0, 256);
377 for (i = 0, str = env; *str != '=' && *str != '\0';)
378 env_name[i++] = *str++;
379
380 env_name[i] = '\0';
381
382 return env_name;
383}
Che-Liang Chioua2a57292011-10-20 23:04:22 +0000384
385/****************************************
386 *
387 * display
388 *
389 ****************************************/
390
391int ub_display_get_info(int type, struct display_info *di)
392{
393 int err = 0;
394
Stanislav Galabov78757d52016-02-17 15:23:31 +0200395 if (!syscall(API_DISPLAY_GET_INFO, &err, type, di))
Che-Liang Chioua2a57292011-10-20 23:04:22 +0000396 return API_ESYSC;
397
398 return err;
399}
400
401int ub_display_draw_bitmap(ulong bitmap, int x, int y)
402{
403 int err = 0;
404
405 if (!syscall(API_DISPLAY_DRAW_BITMAP, &err, bitmap, x, y))
406 return API_ESYSC;
407
408 return err;
409}
410
411void ub_display_clear(void)
412{
413 syscall(API_DISPLAY_CLEAR, NULL);
414}
Rob Clark7e3e2052017-09-09 06:47:43 -0400415
416__weak void *memcpy(void *dest, const void *src, size_t size)
417{
418 unsigned char *dptr = dest;
419 const unsigned char *ptr = src;
420 const unsigned char *end = src + size;
421
422 while (ptr < end)
423 *dptr++ = *ptr++;
424
425 return dest;
426}