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