1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * (C) Copyright 2007-2008 Semihalf, Rafal Jaworowski <raj@semihalf.com>
4 */
5
6 #include <common.h>
7 #include <env.h>
8 #include <linux/types.h>
9 #include <api_public.h>
10 #include <u-boot/crc.h>
11
12 #include "glue.h"
13
valid_sig(struct api_signature * sig)14 static 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 */
api_search_sig(struct api_signature ** sig)42 int api_search_sig(struct api_signature **sig)
43 {
44 unsigned char *sp;
45 uint32_t search_start = 0;
46 uint32_t search_end = 0;
47
48 if (sig == NULL)
49 return 0;
50
51 if (search_hint == 0)
52 search_hint = 255 * 1024 * 1024;
53
54 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) {
59 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
ub_getc(void)77 int ub_getc(void)
78 {
79 int c;
80
81 if (!syscall(API_GETC, NULL, &c))
82 return -1;
83
84 return c;
85 }
86
ub_tstc(void)87 int ub_tstc(void)
88 {
89 int t;
90
91 if (!syscall(API_TSTC, NULL, &t))
92 return -1;
93
94 return t;
95 }
96
ub_putc(char c)97 void ub_putc(char c)
98 {
99 syscall(API_PUTC, NULL, &c);
100 }
101
ub_puts(const char * s)102 void ub_puts(const char *s)
103 {
104 syscall(API_PUTS, NULL, s);
105 }
106
107 /****************************************
108 *
109 * system
110 *
111 ****************************************/
112
ub_reset(void)113 void ub_reset(void)
114 {
115 syscall(API_RESET, NULL);
116 }
117
118 static struct mem_region mr[UB_MAX_MR];
119 static struct sys_info si;
120
ub_get_sys_info(void)121 struct 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;
127 si.mr_no = UB_MAX_MR;
128 memset(&mr, 0, sizeof(mr));
129
130 if (!syscall(API_GET_SYS_INFO, &err, &si))
131 return NULL;
132
133 return ((err) ? NULL : &si);
134 }
135
136 /****************************************
137 *
138 * timing
139 *
140 ****************************************/
141
ub_udelay(unsigned long usec)142 void ub_udelay(unsigned long usec)
143 {
144 syscall(API_UDELAY, NULL, &usec);
145 }
146
ub_get_timer(unsigned long base)147 unsigned 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 *
162 * Devices are identified by handles: numbers 0, 1, 2, ..., UB_MAX_DEV-1
163 *
164 ***************************************************************************/
165
166 static struct device_info devices[UB_MAX_DEV];
167
ub_dev_get(int i)168 struct device_info * ub_dev_get(int i)
169 {
170 return ((i < 0 || i >= UB_MAX_DEV) ? NULL : &devices[i]);
171 }
172
173 /*
174 * Enumerates the devices: fills out device_info elements in the devices[]
175 * array.
176 *
177 * returns: number of devices found
178 */
ub_dev_enum(void)179 int ub_dev_enum(void)
180 {
181 struct device_info *di;
182 int n = 0;
183
184 memset(&devices, 0, sizeof(struct device_info) * UB_MAX_DEV);
185 di = &devices[0];
186
187 if (!syscall(API_DEV_ENUM, NULL, di))
188 return 0;
189
190 while (di->cookie != NULL) {
191
192 if (++n >= UB_MAX_DEV)
193 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 */
ub_dev_open(int handle)213 int ub_dev_open(int handle)
214 {
215 struct device_info *di;
216 int err = 0;
217
218 if (handle < 0 || handle >= UB_MAX_DEV)
219 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
ub_dev_close(int handle)229 int ub_dev_close(int handle)
230 {
231 struct device_info *di;
232
233 if (handle < 0 || handle >= UB_MAX_DEV)
234 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 */
dev_valid(int handle)252 static int dev_valid(int handle)
253 {
254 if (handle < 0 || handle >= UB_MAX_DEV)
255 return 0;
256
257 if (devices[handle].state != DEV_STA_OPEN)
258 return 0;
259
260 return 1;
261 }
262
dev_stor_valid(int handle)263 static 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
ub_dev_read(int handle,void * buf,lbasize_t len,lbastart_t start,lbasize_t * rlen)274 int ub_dev_read(int handle, void *buf, lbasize_t len, lbastart_t start,
275 lbasize_t *rlen)
276 {
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))
286 return API_ESYSC;
287
288 if (!err && rlen)
289 *rlen = act_len;
290
291 return err;
292 }
293
dev_net_valid(int handle)294 static 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
ub_dev_recv(int handle,void * buf,int len,int * rlen)305 int ub_dev_recv(int handle, void *buf, int len, int *rlen)
306 {
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))
315 return API_ESYSC;
316
317 if (!err && rlen)
318 *rlen = act_len;
319
320 return (err);
321 }
322
ub_dev_send(int handle,void * buf,int len)323 int 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))
333 return API_ESYSC;
334
335 return err;
336 }
337
338 /****************************************
339 *
340 * env vars
341 *
342 ****************************************/
343
ub_env_get(const char * name)344 char * ub_env_get(const char *name)
345 {
346 char *value;
347
348 if (!syscall(API_ENV_GET, NULL, name, &value))
349 return NULL;
350
351 return value;
352 }
353
ub_env_set(const char * name,char * value)354 void ub_env_set(const char *name, char *value)
355 {
356 syscall(API_ENV_SET, NULL, name, value);
357 }
358
359 static char env_name[256];
360
ub_env_enum(const char * last)361 const char * ub_env_enum(const char *last)
362 {
363 const char *env, *str;
364 int i;
365
366 env = NULL;
367
368 /*
369 * It's OK to pass only the name piece as last (and not the whole
370 * 'name=val' string), since the API_ENUM_ENV call uses env_match()
371 * internally, which handles such case
372 */
373 if (!syscall(API_ENV_ENUM, NULL, last, &env))
374 return NULL;
375
376 if (!env)
377 /* no more env. variables to enumerate */
378 return NULL;
379
380 /* next enumerated env var */
381 memset(env_name, 0, 256);
382 for (i = 0, str = env; *str != '=' && *str != '\0';)
383 env_name[i++] = *str++;
384
385 env_name[i] = '\0';
386
387 return env_name;
388 }
389
390 /****************************************
391 *
392 * display
393 *
394 ****************************************/
395
ub_display_get_info(int type,struct display_info * di)396 int ub_display_get_info(int type, struct display_info *di)
397 {
398 int err = 0;
399
400 if (!syscall(API_DISPLAY_GET_INFO, &err, type, di))
401 return API_ESYSC;
402
403 return err;
404 }
405
ub_display_draw_bitmap(ulong bitmap,int x,int y)406 int ub_display_draw_bitmap(ulong bitmap, int x, int y)
407 {
408 int err = 0;
409
410 if (!syscall(API_DISPLAY_DRAW_BITMAP, &err, bitmap, x, y))
411 return API_ESYSC;
412
413 return err;
414 }
415
ub_display_clear(void)416 void ub_display_clear(void)
417 {
418 syscall(API_DISPLAY_CLEAR, NULL);
419 }
420
memcpy(void * dest,const void * src,size_t size)421 __weak void *memcpy(void *dest, const void *src, size_t size)
422 {
423 unsigned char *dptr = dest;
424 const unsigned char *ptr = src;
425 const unsigned char *end = src + size;
426
427 while (ptr < end)
428 *dptr++ = *ptr++;
429
430 return dest;
431 }
432