1122715Sbde/*- 2122715Sbde * Copyright (c) 2007-2008 Semihalf, Rafal Jaworowski <raj@semihalf.com> 3122715Sbde * All rights reserved. 4122715Sbde * 5122715Sbde * Redistribution and use in source and binary forms, with or without 685909Simp * modification, are permitted provided that the following conditions 788893Simp * are met: 888893Simp * 1. Redistributions of source code must retain the above copyright 988969Simp * notice, this list of conditions and the following disclaimer. 1085909Simp * 2. Redistributions in binary form must reproduce the above copyright 11115572Sphk * notice, this list of conditions and the following disclaimer in the 12115572Sphk * documentation and/or other materials provided with the distribution. 13115572Sphk * 14115572Sphk * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15191794Sjhb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16191794Sjhb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17115572Sphk * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18205640Snetchild * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19205640Snetchild * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20205640Snetchild * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21205640Snetchild * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22206082Snetchild * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23206082Snetchild * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24206082Snetchild * SUCH DAMAGE. 25206082Snetchild */ 26111211Sru 2785909Simp#include <sys/cdefs.h> 28111802Sru__FBSDID("$FreeBSD$"); 29111802Sru 30111211Sru#include <sys/types.h> 31111211Sru 32111211Sru#include <crc32.h> 33111211Sru#include <stand.h> 34111802Sru#include "api_public.h" 35111802Sru#include "glue.h" 36111211Sru 37111211Sru#ifdef DEBUG 3885909Simp#define debugf(fmt, args...) do { printf("%s(): ", __func__); printf(fmt,##args); } while (0) 39137596Simp#else 40147155Simp#define debugf(fmt, args...) 41137596Simp#endif 42147011Smux 43142424Simp/* Some random address used by U-Boot. */ 44142413Simpextern long uboot_address; 45137596Simp 46147011Smuxstatic int 47137596Simpvalid_sig(struct api_signature *sig) 48137596Simp{ 49137596Simp uint32_t checksum; 50137596Simp struct api_signature s; 51111211Sru 52111211Sru if (sig == NULL) 53167845Simp return (0); 54111211Sru /* 55155427Sru * Clear the checksum field (in the local copy) so as to calculate the 56111802Sru * CRC with the same initial contents as at the time when the sig was 57111802Sru * produced 58111766Sru */ 59111211Sru s = *sig; 60111766Sru s.checksum = 0; 61111766Sru 62111211Sru checksum = crc32((void *)&s, sizeof(struct api_signature)); 63111211Sru 64111211Sru if (checksum != sig->checksum) 65111211Sru return (0); 66111211Sru 67111211Sru return (1); 68111211Sru} 69111211Sru 70151636Simp/* 71151636Simp * Searches for the U-Boot API signature 72151636Simp * 73151636Simp * returns 1/0 depending on found/not found result 74151750Sru */ 75151750Sruint 76151731Sruapi_search_sig(struct api_signature **sig) 77151750Sru{ 78151731Sru unsigned char *sp, *spend; 79151646Sru 80151646Sru if (sig == NULL) 81116252Sgrog return (0); 82123965Sbde 83116252Sgrog if (uboot_address == 0) 84123965Sbde uboot_address = 255 * 1024 * 1024; 85123965Sbde 86135611Sphk sp = (void *)(uboot_address & ~0x000fffff); 87124776Sru spend = sp + 0x00300000 - API_SIG_MAGLEN; 88116252Sgrog while (sp < spend) { 89123965Sbde if (!bcmp(sp, API_SIG_MAGIC, API_SIG_MAGLEN)) { 9085909Simp *sig = (struct api_signature *)sp; 91124776Sru if (valid_sig(*sig)) 9285909Simp return (1); 93151636Simp } 9485909Simp sp += API_SIG_MAGLEN; 9585909Simp } 9685909Simp 97206082Snetchild *sig = NULL; 98125775Sru return (0); 99125775Sru} 100125775Sru 10185909Simp/**************************************** 102159560Scognet * 103175984Sraj * console 104159560Scognet * 10585909Simp ****************************************/ 106116691Sru 107131129Simpint 10885909Simpub_getc(void) 10985909Simp{ 110116341Smarkm int c; 111116341Smarkm 11285909Simp if (!syscall(API_GETC, NULL, (uint32_t)&c)) 113102082Sbde return (-1); 114102082Sbde 115102082Sbde return (c); 116102082Sbde} 11785909Simp 11895844Sobrienint 11985909Simpub_tstc(void) 12085909Simp{ 12185909Simp int t; 12285909Simp 123151750Sru if (!syscall(API_TSTC, NULL, (uint32_t)&t)) 124151731Sru return (-1); 125145416Sru 126123965Sbde return (t); 127163332Sru} 12885909Simp 129116341Smarkmvoid 130123965Sbdeub_putc(char c) 131123965Sbde{ 13292491Smarkm 13385909Simp syscall(API_PUTC, NULL, (uint32_t)&c); 13485909Simp} 13585909Simp 13685909Simpvoid 13785909Simpub_puts(const char *s) 138161283Sdes{ 139123966Sbde 14085909Simp syscall(API_PUTS, NULL, (uint32_t)s); 14185909Simp} 142123965Sbde 14385909Simp/**************************************** 14485909Simp * 14585909Simp * system 146127306Sobrien * 14785909Simp ****************************************/ 14885909Simp 149123985Sbdevoid 15085909Simpub_reset(void) 15185909Simp{ 15285909Simp 153145403Sru syscall(API_RESET, NULL); 154102073Sbde} 15591104Sjake 156152964Srustatic struct mem_region mr[UB_MAX_MR]; 157152964Srustatic struct sys_info si; 158152964Sru 159163332Srustruct sys_info * 16085909Simpub_get_sys_info(void) 161131210Simp{ 162102073Sbde int err = 0; 163111684Sru 164102073Sbde memset(&si, 0, sizeof(struct sys_info)); 16585909Simp si.mr = mr; 16685909Simp si.mr_no = UB_MAX_MR; 16785909Simp memset(&mr, 0, sizeof(mr)); 168152964Sru 169152964Sru if (!syscall(API_GET_SYS_INFO, &err, (u_int32_t)&si)) 170152964Sru return (NULL); 171152964Sru 172152964Sru return ((err) ? NULL : &si); 173152964Sru} 174152964Sru 175152964Sru/**************************************** 176152964Sru * 177152964Sru * timing 178152964Sru * 179152964Sru ****************************************/ 180152964Sru 181152964Sruvoid 182152964Sruub_udelay(unsigned long usec) 183152964Sru{ 184152964Sru 185152964Sru syscall(API_UDELAY, NULL, &usec); 186152964Sru} 187152964Sru 188152964Sruunsigned long 189152964Sruub_get_timer(unsigned long base) 190163332Sru{ 19185909Simp unsigned long cur; 192163332Sru 19385909Simp if (!syscall(API_GET_TIMER, NULL, &cur, &base)) 19485909Simp return (0); 19585909Simp 196123965Sbde return (cur); 19791046Sluigi} 198123965Sbde 199123965Sbde/**************************************************************************** 20085909Simp * 20185909Simp * devices 20285909Simp * 20385909Simp * Devices are identified by handles: numbers 0, 1, 2, ..., UB_MAX_DEV-1 20485909Simp * 20585909Simp ***************************************************************************/ 206127246Smarcel 207151731Srustatic struct device_info devices[UB_MAX_DEV]; 20885909Simp 20985909Simpstruct device_info * 21085909Simpub_dev_get(int i) 21185909Simp{ 21285909Simp 213145623Sru return ((i < 0 || i >= UB_MAX_DEV) ? NULL : &devices[i]); 21485909Simp} 21585909Simp 21685909Simp/* 21785909Simp * Enumerates the devices: fills out device_info elements in the devices[] 21885909Simp * array. 21985909Simp * 22085909Simp * returns: number of devices found 22185909Simp */ 222118633Sruint 22385909Simpub_dev_enum(void) 22485909Simp{ 22585909Simp struct device_info *di; 226186854Sbz int n = 0; 227151636Simp 228186854Sbz memset(&devices, 0, sizeof(struct device_info) * UB_MAX_DEV); 229151636Simp di = &devices[0]; 230167845Simp 231186854Sbz if (!syscall(API_DEV_ENUM, NULL, di)) 232167845Simp return (0); 23385909Simp 234167845Simp while (di->cookie != NULL) { 235167845Simp 23695356Sru if (++n >= UB_MAX_DEV) 23785909Simp break; 238186854Sbz 239151636Simp /* take another device_info */ 240186854Sbz di++; 241151636Simp 24285909Simp /* pass on the previous cookie */ 243144293Sphk di->cookie = devices[n - 1].cookie; 24485909Simp 245206082Snetchild if (!syscall(API_DEV_ENUM, NULL, di)) 24685909Simp return (0); 247144293Sphk } 248116341Smarkm 249116341Smarkm return (n); 25085909Simp} 251135371Sru 25285909Simp/* 25391512Sobrien * handle: 0-based id of the device 25491512Sobrien * 25585909Simp * returns: 0 when OK, err otherwise 256163705Sru */ 257163705Sruint 258163705Sruub_dev_open(int handle) 25991512Sobrien{ 260163705Sru struct device_info *di; 261138290Sphk int err = 0; 262163705Sru 263138290Sphk if (handle < 0 || handle >= UB_MAX_DEV) 26485909Simp return (API_EINVAL); 265116691Sru 266116691Sru di = &devices[handle]; 26785909Simp if (!syscall(API_DEV_OPEN, &err, di)) 268111686Sru return (-1); 269 270 return (err); 271} 272 273int 274ub_dev_close(int handle) 275{ 276 struct device_info *di; 277 278 if (handle < 0 || handle >= UB_MAX_DEV) 279 return (API_EINVAL); 280 281 di = &devices[handle]; 282 if (!syscall(API_DEV_CLOSE, NULL, di)) 283 return (-1); 284 285 return (0); 286} 287 288/* 289 * Validates device for read/write, it has to: 290 * 291 * - have sane handle 292 * - be opened 293 * 294 * returns: 0/1 accordingly 295 */ 296static int 297dev_valid(int handle) 298{ 299 300 if (handle < 0 || handle >= UB_MAX_DEV) 301 return (0); 302 303 if (devices[handle].state != DEV_STA_OPEN) 304 return (0); 305 306 return (1); 307} 308 309static int 310dev_stor_valid(int handle) 311{ 312 313 if (!dev_valid(handle)) 314 return (0); 315 316 if (!(devices[handle].type & DEV_TYP_STOR)) 317 return (0); 318 319 return (1); 320} 321 322int 323ub_dev_read(int handle, void *buf, lbasize_t len, lbastart_t start, 324 lbasize_t *rlen) 325{ 326 struct device_info *di; 327 lbasize_t act_len; 328 int err = 0; 329 330 if (!dev_stor_valid(handle)) 331 return (API_ENODEV); 332 333 di = &devices[handle]; 334 if (!syscall(API_DEV_READ, &err, di, buf, &len, &start, &act_len)) 335 return (API_ESYSC); 336 337 if (!err && rlen) 338 *rlen = act_len; 339 340 return (err); 341} 342 343static int 344dev_net_valid(int handle) 345{ 346 347 if (!dev_valid(handle)) 348 return (0); 349 350 if (devices[handle].type != DEV_TYP_NET) 351 return (0); 352 353 return (1); 354} 355 356int 357ub_dev_recv(int handle, void *buf, int len, int *rlen) 358{ 359 struct device_info *di; 360 int err = 0, act_len; 361 362 if (!dev_net_valid(handle)) 363 return (API_ENODEV); 364 365 di = &devices[handle]; 366 if (!syscall(API_DEV_READ, &err, di, buf, &len, &act_len)) 367 return (API_ESYSC); 368 369 if (!err) 370 *rlen = act_len; 371 372 return (err); 373} 374 375int 376ub_dev_send(int handle, void *buf, int len) 377{ 378 struct device_info *di; 379 int err = 0; 380 381 if (!dev_net_valid(handle)) 382 return (API_ENODEV); 383 384 di = &devices[handle]; 385 if (!syscall(API_DEV_WRITE, &err, di, buf, &len)) 386 return (API_ESYSC); 387 388 return (err); 389} 390 391char * 392ub_stor_type(int type) 393{ 394 395 if (type & DT_STOR_IDE) 396 return ("IDE"); 397 398 if (type & DT_STOR_SCSI) 399 return ("SCSI"); 400 401 if (type & DT_STOR_USB) 402 return ("USB"); 403 404 if (type & DT_STOR_MMC) 405 return ("MMC"); 406 407 if (type & DT_STOR_SATA) 408 return ("SATA"); 409 410 return ("Unknown"); 411} 412 413char * 414ub_mem_type(int flags) 415{ 416 417 switch (flags & 0x000F) { 418 case MR_ATTR_FLASH: 419 return ("FLASH"); 420 case MR_ATTR_DRAM: 421 return ("DRAM"); 422 case MR_ATTR_SRAM: 423 return ("SRAM"); 424 default: 425 return ("Unknown"); 426 } 427} 428 429void 430ub_dump_di(int handle) 431{ 432 struct device_info *di = ub_dev_get(handle); 433 int i; 434 435 printf("device info (%d):\n", handle); 436 printf(" cookie\t= 0x%08x\n", (uint32_t)di->cookie); 437 printf(" type\t\t= 0x%08x\n", di->type); 438 439 if (di->type == DEV_TYP_NET) { 440 printf(" hwaddr\t= "); 441 for (i = 0; i < 6; i++) 442 printf("%02x ", di->di_net.hwaddr[i]); 443 444 printf("\n"); 445 446 } else if (di->type & DEV_TYP_STOR) { 447 printf(" type\t\t= %s\n", ub_stor_type(di->type)); 448 printf(" blk size\t\t= %ld\n", di->di_stor.block_size); 449 printf(" blk count\t\t= %ld\n", di->di_stor.block_count); 450 } 451} 452 453void 454ub_dump_si(struct sys_info *si) 455{ 456 int i; 457 458 printf("sys info:\n"); 459 printf(" clkbus\t= %ld MHz\n", si->clk_bus / 1000 / 1000); 460 printf(" clkcpu\t= %ld MHz\n", si->clk_cpu / 1000 / 1000); 461 printf(" bar\t\t= 0x%08lx\n", si->bar); 462 463 printf("---\n"); 464 for (i = 0; i < si->mr_no; i++) { 465 if (si->mr[i].flags == 0) 466 break; 467 468 printf(" start\t= 0x%08lx\n", si->mr[i].start); 469 printf(" size\t= 0x%08lx\n", si->mr[i].size); 470 printf(" type\t= %s\n", ub_mem_type(si->mr[i].flags)); 471 printf("---\n"); 472 } 473} 474 475/**************************************** 476 * 477 * env vars 478 * 479 ****************************************/ 480 481char * 482ub_env_get(const char *name) 483{ 484 char *value; 485 486 if (!syscall(API_ENV_GET, NULL, (uint32_t)name, (uint32_t)&value)) 487 return (NULL); 488 489 return (value); 490} 491 492void 493ub_env_set(const char *name, char *value) 494{ 495 496 syscall(API_ENV_SET, NULL, (uint32_t)name, (uint32_t)value); 497} 498 499static char env_name[256]; 500 501const char * 502ub_env_enum(const char *last) 503{ 504 const char *env, *str; 505 int i; 506 507 /* 508 * It's OK to pass only the name piece as last (and not the whole 509 * 'name=val' string), since the API_ENUM_ENV call uses envmatch() 510 * internally, which handles such case 511 */ 512 env = NULL; 513 if (!syscall(API_ENV_ENUM, NULL, (uint32_t)last, (uint32_t)&env)) 514 return (NULL); 515 516 if (env == NULL) 517 /* no more env. variables to enumerate */ 518 return (NULL); 519 520 /* next enumerated env var */ 521 memset(env_name, 0, 256); 522 for (i = 0, str = env; *str != '=' && *str != '\0';) 523 env_name[i++] = *str++; 524 525 env_name[i] = '\0'; 526 527 return (env_name); 528} 529