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