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