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