1 /*- 2 * Copyright (c) 2007-2008 Semihalf, Rafal Jaworowski <raj@semihalf.com> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #include <sys/types.h> 28 29 #include <zlib.h> 30 #include <stand.h> 31 #include "api_public.h" 32 #include "glue.h" 33 34 #ifdef DEBUG 35 #define debugf(fmt, args...) do { printf("%s(): ", __func__); printf(fmt,##args); } while (0) 36 #else 37 #define debugf(fmt, args...) 38 #endif 39 40 /* Some random address used by U-Boot. */ 41 extern long uboot_address; 42 43 static int 44 valid_sig(struct api_signature *sig) 45 { 46 uint32_t checksum; 47 struct api_signature s; 48 49 if (sig == NULL) 50 return (0); 51 /* 52 * Clear the checksum field (in the local copy) so as to calculate the 53 * CRC with the same initial contents as at the time when the sig was 54 * produced 55 */ 56 s = *sig; 57 s.checksum = crc32(0, Z_NULL, 0); 58 59 checksum = crc32(s.checksum, (void *)&s, sizeof(struct api_signature)); 60 61 if (checksum != sig->checksum) 62 return (0); 63 64 return (1); 65 } 66 67 /* 68 * Checks to see if API signature's address was given to us as a command line 69 * argument by U-Boot. 70 * 71 * returns 1/0 depending on found/not found result 72 */ 73 int 74 api_parse_cmdline_sig(int argc, char **argv, struct api_signature **sig) 75 { 76 unsigned long api_address; 77 int c; 78 79 api_address = 0; 80 opterr = 0; 81 optreset = 1; 82 optind = 1; 83 84 while ((c = getopt (argc, argv, "a:")) != -1) 85 switch (c) { 86 case 'a': 87 api_address = strtoul(optarg, NULL, 16); 88 break; 89 default: 90 break; 91 } 92 93 if (api_address != 0) { 94 *sig = (struct api_signature *)api_address; 95 if (valid_sig(*sig)) 96 return (1); 97 } 98 99 return (0); 100 } 101 102 /* 103 * Searches for the U-Boot API signature 104 * 105 * returns 1/0 depending on found/not found result 106 */ 107 int 108 api_search_sig(struct api_signature **sig) 109 { 110 unsigned char *sp, *spend; 111 112 if (sig == NULL) 113 return (0); 114 115 if (uboot_address == 0) 116 uboot_address = 255 * 1024 * 1024; 117 118 sp = (void *)(uboot_address & API_SIG_SEARCH_MASK); 119 spend = sp + API_SIG_SEARCH_LEN - API_SIG_MAGLEN; 120 121 while (sp < spend) { 122 if (!bcmp(sp, API_SIG_MAGIC, API_SIG_MAGLEN)) { 123 *sig = (struct api_signature *)sp; 124 if (valid_sig(*sig)) 125 return (1); 126 } 127 sp += API_SIG_MAGLEN; 128 } 129 130 *sig = NULL; 131 return (0); 132 } 133 134 /**************************************** 135 * 136 * console 137 * 138 ****************************************/ 139 140 int 141 ub_getc(void) 142 { 143 int c; 144 145 if (!syscall(API_GETC, NULL, &c)) 146 return (-1); 147 148 return (c); 149 } 150 151 int 152 ub_tstc(void) 153 { 154 int t; 155 156 if (!syscall(API_TSTC, NULL, &t)) 157 return (-1); 158 159 return (t); 160 } 161 162 void 163 ub_putc(const char c) 164 { 165 166 syscall(API_PUTC, NULL, &c); 167 } 168 169 void 170 ub_puts(const char *s) 171 { 172 173 syscall(API_PUTS, NULL, s); 174 } 175 176 /**************************************** 177 * 178 * system 179 * 180 ****************************************/ 181 182 void 183 ub_reset(void) 184 { 185 186 syscall(API_RESET, NULL); 187 while (1); /* fallback if API_RESET failed */ 188 __unreachable(); 189 } 190 191 static struct mem_region mr[UB_MAX_MR]; 192 static struct sys_info si; 193 194 struct sys_info * 195 ub_get_sys_info(void) 196 { 197 int err = 0; 198 199 memset(&si, 0, sizeof(struct sys_info)); 200 si.mr = mr; 201 si.mr_no = UB_MAX_MR; 202 memset(&mr, 0, sizeof(mr)); 203 204 if (!syscall(API_GET_SYS_INFO, &err, &si)) 205 return (NULL); 206 207 return ((err) ? NULL : &si); 208 } 209 210 /**************************************** 211 * 212 * timing 213 * 214 ****************************************/ 215 216 void 217 ub_udelay(unsigned long usec) 218 { 219 220 syscall(API_UDELAY, NULL, &usec); 221 } 222 223 unsigned long 224 ub_get_timer(unsigned long base) 225 { 226 unsigned long cur; 227 228 if (!syscall(API_GET_TIMER, NULL, &cur, &base)) 229 return (0); 230 231 return (cur); 232 } 233 234 /**************************************************************************** 235 * 236 * devices 237 * 238 * Devices are identified by handles: numbers 0, 1, 2, ..., UB_MAX_DEV-1 239 * 240 ***************************************************************************/ 241 242 static struct device_info devices[UB_MAX_DEV]; 243 244 struct device_info * 245 ub_dev_get(int i) 246 { 247 248 return ((i < 0 || i >= UB_MAX_DEV) ? NULL : &devices[i]); 249 } 250 251 /* 252 * Enumerates the devices: fills out device_info elements in the devices[] 253 * array. 254 * 255 * returns: number of devices found 256 */ 257 int 258 ub_dev_enum(void) 259 { 260 struct device_info *di; 261 int n = 0; 262 263 memset(&devices, 0, sizeof(struct device_info) * UB_MAX_DEV); 264 di = &devices[0]; 265 266 if (!syscall(API_DEV_ENUM, NULL, di)) 267 return (0); 268 269 while (di->cookie != NULL) { 270 271 if (++n >= UB_MAX_DEV) 272 break; 273 274 /* take another device_info */ 275 di++; 276 277 /* pass on the previous cookie */ 278 di->cookie = devices[n - 1].cookie; 279 280 if (!syscall(API_DEV_ENUM, NULL, di)) 281 return (0); 282 } 283 284 return (n); 285 } 286 287 /* 288 * handle: 0-based id of the device 289 * 290 * returns: 0 when OK, err otherwise 291 */ 292 int 293 ub_dev_open(int handle) 294 { 295 struct device_info *di; 296 int err = 0; 297 298 if (handle < 0 || handle >= UB_MAX_DEV) 299 return (API_EINVAL); 300 301 di = &devices[handle]; 302 if (!syscall(API_DEV_OPEN, &err, di)) 303 return (-1); 304 305 return (err); 306 } 307 308 int 309 ub_dev_close(int handle) 310 { 311 struct device_info *di; 312 313 if (handle < 0 || handle >= UB_MAX_DEV) 314 return (API_EINVAL); 315 316 di = &devices[handle]; 317 if (!syscall(API_DEV_CLOSE, NULL, di)) 318 return (-1); 319 320 return (0); 321 } 322 323 /* 324 * Validates device for read/write, it has to: 325 * 326 * - have sane handle 327 * - be opened 328 * 329 * returns: 0/1 accordingly 330 */ 331 static int 332 dev_valid(int handle) 333 { 334 335 if (handle < 0 || handle >= UB_MAX_DEV) 336 return (0); 337 338 if (devices[handle].state != DEV_STA_OPEN) 339 return (0); 340 341 return (1); 342 } 343 344 static int 345 dev_stor_valid(int handle) 346 { 347 348 if (!dev_valid(handle)) 349 return (0); 350 351 if (!(devices[handle].type & DEV_TYP_STOR)) 352 return (0); 353 354 return (1); 355 } 356 357 int 358 ub_dev_read(int handle, void *buf, lbasize_t len, lbastart_t start, 359 lbasize_t *rlen) 360 { 361 struct device_info *di; 362 lbasize_t act_len; 363 int err = 0; 364 365 if (!dev_stor_valid(handle)) 366 return (API_ENODEV); 367 368 di = &devices[handle]; 369 if (!syscall(API_DEV_READ, &err, di, buf, &len, &start, &act_len)) 370 return (API_ESYSC); 371 372 if (!err && rlen) 373 *rlen = act_len; 374 375 return (err); 376 } 377 378 static int 379 dev_net_valid(int handle) 380 { 381 382 if (!dev_valid(handle)) 383 return (0); 384 385 if (devices[handle].type != DEV_TYP_NET) 386 return (0); 387 388 return (1); 389 } 390 391 int 392 ub_dev_recv(int handle, void *buf, int len, int *rlen) 393 { 394 struct device_info *di; 395 int err = 0, act_len; 396 397 if (!dev_net_valid(handle)) 398 return (API_ENODEV); 399 400 di = &devices[handle]; 401 if (!syscall(API_DEV_READ, &err, di, buf, &len, &act_len)) 402 return (API_ESYSC); 403 404 if (!err) 405 *rlen = act_len; 406 407 return (err); 408 } 409 410 int 411 ub_dev_send(int handle, void *buf, int len) 412 { 413 struct device_info *di; 414 int err = 0; 415 416 if (!dev_net_valid(handle)) 417 return (API_ENODEV); 418 419 di = &devices[handle]; 420 if (!syscall(API_DEV_WRITE, &err, di, buf, &len)) 421 return (API_ESYSC); 422 423 return (err); 424 } 425 426 char * 427 ub_stor_type(int type) 428 { 429 430 if (type & DT_STOR_IDE) 431 return ("IDE"); 432 433 if (type & DT_STOR_SCSI) 434 return ("SCSI"); 435 436 if (type & DT_STOR_USB) 437 return ("USB"); 438 439 if (type & DT_STOR_MMC) 440 return ("MMC"); 441 442 if (type & DT_STOR_SATA) 443 return ("SATA"); 444 445 return ("Unknown"); 446 } 447 448 char * 449 ub_mem_type(int flags) 450 { 451 452 switch (flags & 0x000F) { 453 case MR_ATTR_FLASH: 454 return ("FLASH"); 455 case MR_ATTR_DRAM: 456 return ("DRAM"); 457 case MR_ATTR_SRAM: 458 return ("SRAM"); 459 default: 460 return ("Unknown"); 461 } 462 } 463 464 void 465 ub_dump_di(int handle) 466 { 467 struct device_info *di = ub_dev_get(handle); 468 int i; 469 470 printf("device info (%d):\n", handle); 471 printf(" cookie\t= %p\n", di->cookie); 472 printf(" type\t\t= 0x%08x\n", di->type); 473 474 if (di->type == DEV_TYP_NET) { 475 printf(" hwaddr\t= "); 476 for (i = 0; i < 6; i++) 477 printf("%02x ", di->di_net.hwaddr[i]); 478 479 printf("\n"); 480 481 } else if (di->type & DEV_TYP_STOR) { 482 printf(" type\t\t= %s\n", ub_stor_type(di->type)); 483 printf(" blk size\t\t= %ld\n", di->di_stor.block_size); 484 printf(" blk count\t\t= %ld\n", di->di_stor.block_count); 485 } 486 } 487 488 void 489 ub_dump_si(struct sys_info *si) 490 { 491 int i; 492 493 printf("sys info:\n"); 494 printf(" clkbus\t= %ld MHz\n", si->clk_bus / 1000 / 1000); 495 printf(" clkcpu\t= %ld MHz\n", si->clk_cpu / 1000 / 1000); 496 printf(" bar\t\t= 0x%08lx\n", si->bar); 497 498 printf("---\n"); 499 for (i = 0; i < si->mr_no; i++) { 500 if (si->mr[i].flags == 0) 501 break; 502 503 printf(" start\t= 0x%08lx\n", si->mr[i].start); 504 printf(" size\t= 0x%08lx\n", si->mr[i].size); 505 printf(" type\t= %s\n", ub_mem_type(si->mr[i].flags)); 506 printf("---\n"); 507 } 508 } 509 510 /**************************************** 511 * 512 * env vars 513 * 514 ****************************************/ 515 516 char * 517 ub_env_get(const char *name) 518 { 519 char *value; 520 521 if (!syscall(API_ENV_GET, NULL, name, &value)) 522 return (NULL); 523 524 return (value); 525 } 526 527 void 528 ub_env_set(const char *name, char *value) 529 { 530 531 syscall(API_ENV_SET, NULL, name, value); 532 } 533 534 static char env_name[256]; 535 536 const char * 537 ub_env_enum(const char *last) 538 { 539 const char *env, *str; 540 int i; 541 542 /* 543 * It's OK to pass only the name piece as last (and not the whole 544 * 'name=val' string), since the API_ENUM_ENV call uses envmatch() 545 * internally, which handles such case 546 */ 547 env = NULL; 548 if (!syscall(API_ENV_ENUM, NULL, last, &env)) 549 return (NULL); 550 551 if (env == NULL || last == env) 552 /* no more env. variables to enumerate */ 553 return (NULL); 554 555 /* next enumerated env var */ 556 memset(env_name, 0, 256); 557 for (i = 0, str = env; *str != '=' && *str != '\0';) 558 env_name[i++] = *str++; 559 560 env_name[i] = '\0'; 561 562 return (env_name); 563 } 564