Blame view
examples/api/glue.c
7.14 KB
500856eb1
|
1 |
/* |
923aa4812
|
2 |
* (C) Copyright 2007-2008 Semihalf, Rafal Jaworowski <raj@semihalf.com> |
500856eb1
|
3 |
* |
1a4596601
|
4 |
* SPDX-License-Identifier: GPL-2.0+ |
500856eb1
|
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
*/ #include <common.h> #include <linux/types.h> #include <api_public.h> #include "glue.h" static int valid_sig(struct api_signature *sig) { uint32_t checksum; struct api_signature s; if (sig == NULL) return 0; /* * Clear the checksum field (in the local copy) so as to calculate the * CRC with the same initial contents as at the time when the sig was * produced */ s = *sig; s.checksum = 0; checksum = crc32(0, (unsigned char *)&s, sizeof(struct api_signature)); if (checksum != sig->checksum) return 0; return 1; } /* * Searches for the U-Boot API signature * * returns 1/0 depending on found/not found result */ |
923aa4812
|
41 42 |
int api_search_sig(struct api_signature **sig) { |
500856eb1
|
43 |
unsigned char *sp; |
b84d7d8f1
|
44 45 |
uint32_t search_start = 0; uint32_t search_end = 0; |
500856eb1
|
46 47 48 |
if (sig == NULL) return 0; |
b84d7d8f1
|
49 50 |
if (search_hint == 0) search_hint = 255 * 1024 * 1024; |
500856eb1
|
51 |
|
b84d7d8f1
|
52 53 54 55 56 |
search_start = search_hint & ~0x000fffff; search_end = search_start + API_SEARCH_LEN - API_SIG_MAGLEN; sp = (unsigned char *)search_start; while ((sp + API_SIG_MAGLEN) < (unsigned char *)search_end) { |
500856eb1
|
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
if (!memcmp(sp, API_SIG_MAGIC, API_SIG_MAGLEN)) { *sig = (struct api_signature *)sp; if (valid_sig(*sig)) return 1; } sp += API_SIG_MAGLEN; } *sig = NULL; return 0; } /**************************************** * * console * ****************************************/ int ub_getc(void) { int c; |
78757d52c
|
78 |
if (!syscall(API_GETC, NULL, &c)) |
500856eb1
|
79 80 81 82 83 84 85 86 |
return -1; return c; } int ub_tstc(void) { int t; |
78757d52c
|
87 |
if (!syscall(API_TSTC, NULL, &t)) |
500856eb1
|
88 89 90 91 92 93 94 |
return -1; return t; } void ub_putc(char c) { |
78757d52c
|
95 |
syscall(API_PUTC, NULL, &c); |
500856eb1
|
96 97 98 99 |
} void ub_puts(const char *s) { |
78757d52c
|
100 |
syscall(API_PUTS, NULL, s); |
500856eb1
|
101 102 103 104 105 106 107 108 109 110 111 112 |
} /**************************************** * * system * ****************************************/ void ub_reset(void) { syscall(API_RESET, NULL); } |
923aa4812
|
113 |
static struct mem_region mr[UB_MAX_MR]; |
500856eb1
|
114 115 116 117 118 119 120 121 |
static struct sys_info si; struct sys_info * ub_get_sys_info(void) { int err = 0; memset(&si, 0, sizeof(struct sys_info)); si.mr = mr; |
923aa4812
|
122 |
si.mr_no = UB_MAX_MR; |
500856eb1
|
123 |
memset(&mr, 0, sizeof(mr)); |
78757d52c
|
124 |
if (!syscall(API_GET_SYS_INFO, &err, &si)) |
500856eb1
|
125 126 127 128 129 130 131 132 133 134 |
return NULL; return ((err) ? NULL : &si); } /**************************************** * * timing * ****************************************/ |
d3a6532cb
|
135 |
|
500856eb1
|
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
void ub_udelay(unsigned long usec) { syscall(API_UDELAY, NULL, &usec); } unsigned long ub_get_timer(unsigned long base) { unsigned long cur; if (!syscall(API_GET_TIMER, NULL, &cur, &base)) return 0; return cur; } /**************************************************************************** * * devices * |
923aa4812
|
156 |
* Devices are identified by handles: numbers 0, 1, 2, ..., UB_MAX_DEV-1 |
500856eb1
|
157 158 |
* ***************************************************************************/ |
923aa4812
|
159 |
static struct device_info devices[UB_MAX_DEV]; |
500856eb1
|
160 161 162 |
struct device_info * ub_dev_get(int i) { |
923aa4812
|
163 |
return ((i < 0 || i >= UB_MAX_DEV) ? NULL : &devices[i]); |
500856eb1
|
164 165 166 167 168 169 170 171 172 173 174 175 |
} /* * Enumerates the devices: fills out device_info elements in the devices[] * array. * * returns: number of devices found */ int ub_dev_enum(void) { struct device_info *di; int n = 0; |
923aa4812
|
176 |
memset(&devices, 0, sizeof(struct device_info) * UB_MAX_DEV); |
500856eb1
|
177 178 179 180 181 182 |
di = &devices[0]; if (!syscall(API_DEV_ENUM, NULL, di)) return 0; while (di->cookie != NULL) { |
923aa4812
|
183 |
if (++n >= UB_MAX_DEV) |
500856eb1
|
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 |
break; /* take another device_info */ di++; /* pass on the previous cookie */ di->cookie = devices[n - 1].cookie; if (!syscall(API_DEV_ENUM, NULL, di)) return 0; } return n; } /* * handle: 0-based id of the device * * returns: 0 when OK, err otherwise */ int ub_dev_open(int handle) { struct device_info *di; int err = 0; |
923aa4812
|
208 |
if (handle < 0 || handle >= UB_MAX_DEV) |
500856eb1
|
209 210 211 212 213 214 215 216 217 218 219 220 221 |
return API_EINVAL; di = &devices[handle]; if (!syscall(API_DEV_OPEN, &err, di)) return -1; return err; } int ub_dev_close(int handle) { struct device_info *di; |
923aa4812
|
222 |
if (handle < 0 || handle >= UB_MAX_DEV) |
500856eb1
|
223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 |
return API_EINVAL; di = &devices[handle]; if (!syscall(API_DEV_CLOSE, NULL, di)) return -1; return 0; } /* * * Validates device for read/write, it has to: * * - have sane handle * - be opened * * returns: 0/1 accordingly */ static int dev_valid(int handle) { |
923aa4812
|
243 |
if (handle < 0 || handle >= UB_MAX_DEV) |
500856eb1
|
244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 |
return 0; if (devices[handle].state != DEV_STA_OPEN) return 0; return 1; } static int dev_stor_valid(int handle) { if (!dev_valid(handle)) return 0; if (!(devices[handle].type & DEV_TYP_STOR)) return 0; return 1; } |
923aa4812
|
262 263 |
int ub_dev_read(int handle, void *buf, lbasize_t len, lbastart_t start, lbasize_t *rlen) |
500856eb1
|
264 265 266 267 268 269 270 271 272 273 |
{ struct device_info *di; lbasize_t act_len; int err = 0; if (!dev_stor_valid(handle)) return API_ENODEV; di = &devices[handle]; if (!syscall(API_DEV_READ, &err, di, buf, &len, &start, &act_len)) |
923aa4812
|
274 |
return API_ESYSC; |
500856eb1
|
275 |
|
923aa4812
|
276 277 |
if (!err && rlen) *rlen = act_len; |
500856eb1
|
278 |
|
923aa4812
|
279 |
return err; |
500856eb1
|
280 281 282 283 284 285 286 287 288 289 290 291 |
} static int dev_net_valid(int handle) { if (!dev_valid(handle)) return 0; if (devices[handle].type != DEV_TYP_NET) return 0; return 1; } |
923aa4812
|
292 |
int ub_dev_recv(int handle, void *buf, int len, int *rlen) |
500856eb1
|
293 294 295 296 297 298 299 300 301 |
{ struct device_info *di; int err = 0, act_len; if (!dev_net_valid(handle)) return API_ENODEV; di = &devices[handle]; if (!syscall(API_DEV_READ, &err, di, buf, &len, &act_len)) |
923aa4812
|
302 |
return API_ESYSC; |
500856eb1
|
303 |
|
923aa4812
|
304 305 |
if (!err && rlen) *rlen = act_len; |
500856eb1
|
306 |
|
923aa4812
|
307 |
return (err); |
500856eb1
|
308 309 310 311 312 313 314 315 316 317 318 319 |
} int ub_dev_send(int handle, void *buf, int len) { struct device_info *di; int err = 0; if (!dev_net_valid(handle)) return API_ENODEV; di = &devices[handle]; if (!syscall(API_DEV_WRITE, &err, di, buf, &len)) |
923aa4812
|
320 |
return API_ESYSC; |
500856eb1
|
321 322 323 324 325 326 327 328 329 330 331 332 333 |
return err; } /**************************************** * * env vars * ****************************************/ char * ub_env_get(const char *name) { char *value; |
78757d52c
|
334 |
if (!syscall(API_ENV_GET, NULL, name, &value)) |
500856eb1
|
335 336 337 338 339 340 341 |
return NULL; return value; } void ub_env_set(const char *name, char *value) { |
78757d52c
|
342 |
syscall(API_ENV_SET, NULL, name, value); |
500856eb1
|
343 |
} |
500856eb1
|
344 345 346 347 348 349 350 351 352 353 354 355 356 357 |
static char env_name[256]; const char * ub_env_enum(const char *last) { const char *env, *str; int i; env = NULL; /* * It's OK to pass only the name piece as last (and not the whole * 'name=val' string), since the API_ENUM_ENV call uses envmatch() * internally, which handles such case */ |
78757d52c
|
358 |
if (!syscall(API_ENV_ENUM, NULL, last, &env)) |
500856eb1
|
359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 |
return NULL; if (!env) /* no more env. variables to enumerate */ return NULL; /* next enumerated env var */ memset(env_name, 0, 256); for (i = 0, str = env; *str != '=' && *str != '\0';) env_name[i++] = *str++; env_name[i] = '\0'; return env_name; } |
a2a5729fc
|
374 375 376 377 378 379 380 381 382 383 |
/**************************************** * * display * ****************************************/ int ub_display_get_info(int type, struct display_info *di) { int err = 0; |
78757d52c
|
384 |
if (!syscall(API_DISPLAY_GET_INFO, &err, type, di)) |
a2a5729fc
|
385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 |
return API_ESYSC; return err; } int ub_display_draw_bitmap(ulong bitmap, int x, int y) { int err = 0; if (!syscall(API_DISPLAY_DRAW_BITMAP, &err, bitmap, x, y)) return API_ESYSC; return err; } void ub_display_clear(void) { syscall(API_DISPLAY_CLEAR, NULL); } |
7e3e20560
|
404 405 406 407 408 409 410 411 412 413 414 415 |
__weak void *memcpy(void *dest, const void *src, size_t size) { unsigned char *dptr = dest; const unsigned char *ptr = src; const unsigned char *end = src + size; while (ptr < end) *dptr++ = *ptr++; return dest; } |