1176348Smarcel/*- 2182732Sraj * Copyright (c) 2007-2008 Semihalf, Rafal Jaworowski <raj@semihalf.com> 3176348Smarcel * All rights reserved. 4176348Smarcel * 5176348Smarcel * Redistribution and use in source and binary forms, with or without 6176348Smarcel * modification, are permitted provided that the following conditions 7176348Smarcel * are met: 8176348Smarcel * 1. Redistributions of source code must retain the above copyright 9176348Smarcel * notice, this list of conditions and the following disclaimer. 10176348Smarcel * 2. Redistributions in binary form must reproduce the above copyright 11176348Smarcel * notice, this list of conditions and the following disclaimer in the 12176348Smarcel * documentation and/or other materials provided with the distribution. 13176348Smarcel * 14176348Smarcel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15176348Smarcel * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16176348Smarcel * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17176348Smarcel * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18176348Smarcel * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19176348Smarcel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20176348Smarcel * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21176348Smarcel * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22176348Smarcel * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23176348Smarcel * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24176348Smarcel * SUCH DAMAGE. 25176348Smarcel */ 26176348Smarcel 27176348Smarcel#include <sys/cdefs.h> 28176348Smarcel__FBSDID("$FreeBSD$"); 29176348Smarcel 30233719Smarius#include <sys/types.h> 31233719Smarius 32233719Smarius#include <crc32.h> 33176348Smarcel#include <stand.h> 34176348Smarcel#include "api_public.h" 35176481Smarcel#include "glue.h" 36176348Smarcel 37176481Smarcel#define DEBUG 38176348Smarcel#undef DEBUG 39176348Smarcel 40176348Smarcel#ifdef DEBUG 41177152Sobrien#define debugf(fmt, args...) do { printf("%s(): ", __func__); printf(fmt,##args); } while (0) 42176348Smarcel#else 43177152Sobrien#define debugf(fmt, args...) 44176348Smarcel#endif 45176348Smarcel 46176481Smarcel/* Some random address used by U-Boot. */ 47182732Srajextern long uboot_address; 48176348Smarcel 49177152Sobrienstatic int 50177152Sobrienvalid_sig(struct api_signature *sig) 51176348Smarcel{ 52176348Smarcel uint32_t checksum; 53176348Smarcel struct api_signature s; 54176348Smarcel 55176348Smarcel if (sig == NULL) 56177108Sraj return (0); 57176348Smarcel /* 58176348Smarcel * Clear the checksum field (in the local copy) so as to calculate the 59176348Smarcel * CRC with the same initial contents as at the time when the sig was 60176348Smarcel * produced 61176348Smarcel */ 62176348Smarcel s = *sig; 63176348Smarcel s.checksum = 0; 64176348Smarcel 65176348Smarcel checksum = crc32((void *)&s, sizeof(struct api_signature)); 66176348Smarcel 67176348Smarcel if (checksum != sig->checksum) 68177108Sraj return (0); 69176348Smarcel 70177108Sraj return (1); 71176348Smarcel} 72176348Smarcel 73176348Smarcel/* 74176348Smarcel * Searches for the U-Boot API signature 75176348Smarcel * 76176348Smarcel * returns 1/0 depending on found/not found result 77176348Smarcel */ 78177152Sobrienint 79177152Sobrienapi_search_sig(struct api_signature **sig) 80177152Sobrien{ 81176481Smarcel unsigned char *sp, *spend; 82176348Smarcel 83176348Smarcel if (sig == NULL) 84177108Sraj return (0); 85176348Smarcel 86176481Smarcel if (uboot_address == 0) 87176481Smarcel uboot_address = 255 * 1024 * 1024; 88176348Smarcel 89176481Smarcel sp = (void *)(uboot_address & ~0x000fffff); 90183878Sraj spend = sp + 0x00300000 - API_SIG_MAGLEN; 91176481Smarcel while (sp < spend) { 92176348Smarcel if (!bcmp(sp, API_SIG_MAGIC, API_SIG_MAGLEN)) { 93176348Smarcel *sig = (struct api_signature *)sp; 94176348Smarcel if (valid_sig(*sig)) 95177108Sraj return (1); 96176348Smarcel } 97176348Smarcel sp += API_SIG_MAGLEN; 98176348Smarcel } 99176348Smarcel 100176348Smarcel *sig = NULL; 101177108Sraj return (0); 102176348Smarcel} 103176348Smarcel 104176348Smarcel/**************************************** 105176348Smarcel * 106176348Smarcel * console 107176348Smarcel * 108176348Smarcel ****************************************/ 109176348Smarcel 110177152Sobrienint 111177152Sobrienub_getc(void) 112176348Smarcel{ 113176348Smarcel int c; 114176348Smarcel 115176348Smarcel if (!syscall(API_GETC, NULL, (uint32_t)&c)) 116177108Sraj return (-1); 117177108Sraj 118182732Sraj return (c); 119176348Smarcel} 120176348Smarcel 121177152Sobrienint 122177152Sobrienub_tstc(void) 123176348Smarcel{ 124176348Smarcel int t; 125176348Smarcel 126176348Smarcel if (!syscall(API_TSTC, NULL, (uint32_t)&t)) 127177108Sraj return (-1); 128176348Smarcel 129182732Sraj return (t); 130176348Smarcel} 131176348Smarcel 132177152Sobrienvoid 133177152Sobrienub_putc(char c) 134176348Smarcel{ 135177152Sobrien 136176348Smarcel syscall(API_PUTC, NULL, (uint32_t)&c); 137176348Smarcel} 138176348Smarcel 139177152Sobrienvoid 140177152Sobrienub_puts(const char *s) 141176348Smarcel{ 142177152Sobrien 143176348Smarcel syscall(API_PUTS, NULL, (uint32_t)s); 144176348Smarcel} 145176348Smarcel 146176348Smarcel/**************************************** 147176348Smarcel * 148176348Smarcel * system 149176348Smarcel * 150176348Smarcel ****************************************/ 151176348Smarcel 152177152Sobrienvoid 153177152Sobrienub_reset(void) 154176348Smarcel{ 155177152Sobrien 156176348Smarcel syscall(API_RESET, NULL); 157176348Smarcel} 158176348Smarcel 159183598Srajstatic struct mem_region mr[UB_MAX_MR]; 160176348Smarcelstatic struct sys_info si; 161176348Smarcel 162177152Sobrienstruct sys_info * 163177152Sobrienub_get_sys_info(void) 164176348Smarcel{ 165176348Smarcel int err = 0; 166177152Sobrien 167176348Smarcel memset(&si, 0, sizeof(struct sys_info)); 168176348Smarcel si.mr = mr; 169183598Sraj si.mr_no = UB_MAX_MR; 170176348Smarcel memset(&mr, 0, sizeof(mr)); 171177152Sobrien 172176348Smarcel if (!syscall(API_GET_SYS_INFO, &err, (u_int32_t)&si)) 173177108Sraj return (NULL); 174176348Smarcel 175176348Smarcel return ((err) ? NULL : &si); 176176348Smarcel} 177176348Smarcel 178176348Smarcel/**************************************** 179176348Smarcel * 180176348Smarcel * timing 181176348Smarcel * 182176348Smarcel ****************************************/ 183177108Sraj 184177152Sobrienvoid 185177152Sobrienub_udelay(unsigned long usec) 186176348Smarcel{ 187177108Sraj 188176348Smarcel syscall(API_UDELAY, NULL, &usec); 189176348Smarcel} 190176348Smarcel 191177152Sobrienunsigned long 192177152Sobrienub_get_timer(unsigned long base) 193176348Smarcel{ 194176348Smarcel unsigned long cur; 195177152Sobrien 196176348Smarcel if (!syscall(API_GET_TIMER, NULL, &cur, &base)) 197177108Sraj return (0); 198176348Smarcel 199177108Sraj return (cur); 200176348Smarcel} 201176348Smarcel 202176348Smarcel/**************************************************************************** 203176348Smarcel * 204176348Smarcel * devices 205176348Smarcel * 206183598Sraj * Devices are identified by handles: numbers 0, 1, 2, ..., UB_MAX_DEV-1 207176348Smarcel * 208176348Smarcel ***************************************************************************/ 209176348Smarcel 210183598Srajstatic struct device_info devices[UB_MAX_DEV]; 211176348Smarcel 212177152Sobrienstruct device_info * 213177152Sobrienub_dev_get(int i) 214176348Smarcel{ 215177152Sobrien 216183598Sraj return ((i < 0 || i >= UB_MAX_DEV) ? NULL : &devices[i]); 217176348Smarcel} 218176348Smarcel 219176348Smarcel/* 220176348Smarcel * Enumerates the devices: fills out device_info elements in the devices[] 221176348Smarcel * array. 222176348Smarcel * 223176348Smarcel * returns: number of devices found 224176348Smarcel */ 225177152Sobrienint 226177152Sobrienub_dev_enum(void) 227176348Smarcel{ 228176348Smarcel struct device_info *di; 229176348Smarcel int n = 0; 230176348Smarcel 231183598Sraj memset(&devices, 0, sizeof(struct device_info) * UB_MAX_DEV); 232176348Smarcel di = &devices[0]; 233176348Smarcel 234176348Smarcel if (!syscall(API_DEV_ENUM, NULL, di)) 235177108Sraj return (0); 236176348Smarcel 237176348Smarcel while (di->cookie != NULL) { 238176348Smarcel 239183598Sraj if (++n >= UB_MAX_DEV) 240176348Smarcel break; 241176348Smarcel 242176348Smarcel /* take another device_info */ 243176348Smarcel di++; 244176348Smarcel 245176348Smarcel /* pass on the previous cookie */ 246176348Smarcel di->cookie = devices[n - 1].cookie; 247176348Smarcel 248176348Smarcel if (!syscall(API_DEV_ENUM, NULL, di)) 249182732Sraj return (0); 250177108Sraj } 251176348Smarcel 252177108Sraj return (n); 253176348Smarcel} 254176348Smarcel 255176348Smarcel/* 256176348Smarcel * handle: 0-based id of the device 257176348Smarcel * 258176348Smarcel * returns: 0 when OK, err otherwise 259176348Smarcel */ 260177152Sobrienint 261177152Sobrienub_dev_open(int handle) 262176348Smarcel{ 263176348Smarcel struct device_info *di; 264176348Smarcel int err = 0; 265176348Smarcel 266183598Sraj if (handle < 0 || handle >= UB_MAX_DEV) 267177108Sraj return (API_EINVAL); 268176348Smarcel 269176348Smarcel di = &devices[handle]; 270176348Smarcel if (!syscall(API_DEV_OPEN, &err, di)) 271177108Sraj return (-1); 272176348Smarcel 273177108Sraj return (err); 274176348Smarcel} 275176348Smarcel 276177152Sobrienint 277177152Sobrienub_dev_close(int handle) 278176348Smarcel{ 279176348Smarcel struct device_info *di; 280176348Smarcel 281183598Sraj if (handle < 0 || handle >= UB_MAX_DEV) 282177108Sraj return (API_EINVAL); 283176348Smarcel 284176348Smarcel di = &devices[handle]; 285176348Smarcel if (!syscall(API_DEV_CLOSE, NULL, di)) 286177108Sraj return (-1); 287176348Smarcel 288177108Sraj return (0); 289176348Smarcel} 290176348Smarcel 291176348Smarcel/* 292176348Smarcel * Validates device for read/write, it has to: 293176348Smarcel * 294176348Smarcel * - have sane handle 295176348Smarcel * - be opened 296176348Smarcel * 297176348Smarcel * returns: 0/1 accordingly 298176348Smarcel */ 299177152Sobrienstatic int 300177152Sobriendev_valid(int handle) 301176348Smarcel{ 302177108Sraj 303183598Sraj if (handle < 0 || handle >= UB_MAX_DEV) 304177108Sraj return (0); 305176348Smarcel 306176348Smarcel if (devices[handle].state != DEV_STA_OPEN) 307177108Sraj return (0); 308176348Smarcel 309177108Sraj return (1); 310176348Smarcel} 311176348Smarcel 312177152Sobrienstatic int 313177152Sobriendev_stor_valid(int handle) 314176348Smarcel{ 315177108Sraj 316176348Smarcel if (!dev_valid(handle)) 317177108Sraj return (0); 318176348Smarcel 319176348Smarcel if (!(devices[handle].type & DEV_TYP_STOR)) 320177108Sraj return (0); 321176348Smarcel 322177108Sraj return (1); 323176348Smarcel} 324176348Smarcel 325177152Sobrienint 326183598Srajub_dev_read(int handle, void *buf, lbasize_t len, lbastart_t start, 327183598Sraj lbasize_t *rlen) 328176348Smarcel{ 329176348Smarcel struct device_info *di; 330176348Smarcel lbasize_t act_len; 331176348Smarcel int err = 0; 332176348Smarcel 333176348Smarcel if (!dev_stor_valid(handle)) 334177108Sraj return (API_ENODEV); 335176348Smarcel 336176348Smarcel di = &devices[handle]; 337176348Smarcel if (!syscall(API_DEV_READ, &err, di, buf, &len, &start, &act_len)) 338183598Sraj return (API_ESYSC); 339176348Smarcel 340183598Sraj if (!err && rlen) 341183598Sraj *rlen = act_len; 342176348Smarcel 343183598Sraj return (err); 344176348Smarcel} 345176348Smarcel 346177152Sobrienstatic int 347177152Sobriendev_net_valid(int handle) 348176348Smarcel{ 349177108Sraj 350176348Smarcel if (!dev_valid(handle)) 351177108Sraj return (0); 352176348Smarcel 353176348Smarcel if (devices[handle].type != DEV_TYP_NET) 354177108Sraj return (0); 355176348Smarcel 356177108Sraj return (1); 357176348Smarcel} 358176348Smarcel 359177152Sobrienint 360183598Srajub_dev_recv(int handle, void *buf, int len, int *rlen) 361176348Smarcel{ 362176348Smarcel struct device_info *di; 363176348Smarcel int err = 0, act_len; 364176348Smarcel 365176348Smarcel if (!dev_net_valid(handle)) 366177108Sraj return (API_ENODEV); 367176348Smarcel 368176348Smarcel di = &devices[handle]; 369176348Smarcel if (!syscall(API_DEV_READ, &err, di, buf, &len, &act_len)) 370183598Sraj return (API_ESYSC); 371176348Smarcel 372183598Sraj if (!err) 373183598Sraj *rlen = act_len; 374176348Smarcel 375183598Sraj return (err); 376176348Smarcel} 377176348Smarcel 378177152Sobrienint 379177152Sobrienub_dev_send(int handle, void *buf, int len) 380176348Smarcel{ 381176348Smarcel struct device_info *di; 382176348Smarcel int err = 0; 383176348Smarcel 384176348Smarcel if (!dev_net_valid(handle)) 385177108Sraj return (API_ENODEV); 386176348Smarcel 387176348Smarcel di = &devices[handle]; 388176348Smarcel if (!syscall(API_DEV_WRITE, &err, di, buf, &len)) 389183598Sraj return (API_ESYSC); 390176348Smarcel 391177108Sraj return (err); 392176348Smarcel} 393176348Smarcel 394185099Srajchar * 395182732Srajub_stor_type(int type) 396182732Sraj{ 397182732Sraj 398182732Sraj if (type & DT_STOR_IDE) 399182732Sraj return ("IDE"); 400182732Sraj 401182732Sraj if (type & DT_STOR_SCSI) 402182732Sraj return ("SCSI"); 403182732Sraj 404182732Sraj if (type & DT_STOR_USB) 405182732Sraj return ("USB"); 406182732Sraj 407199193Santoine if (type & DT_STOR_MMC) 408182732Sraj return ("MMC"); 409182732Sraj 410182732Sraj return ("Unknown"); 411182732Sraj} 412182732Sraj 413182732Srajchar * 414182732Srajub_mem_type(int flags) 415182732Sraj{ 416182732Sraj 417183599Sraj switch (flags & 0x000F) { 418182732Sraj case MR_ATTR_FLASH: 419182732Sraj return ("FLASH"); 420182732Sraj case MR_ATTR_DRAM: 421182732Sraj return ("DRAM"); 422182732Sraj case MR_ATTR_SRAM: 423182732Sraj return ("SRAM"); 424182732Sraj default: 425182732Sraj return ("Unknown"); 426182732Sraj } 427182732Sraj} 428182732Sraj 429182732Srajvoid 430182732Srajub_dump_di(int handle) 431182732Sraj{ 432182732Sraj struct device_info *di = ub_dev_get(handle); 433182732Sraj int i; 434182732Sraj 435182732Sraj printf("device info (%d):\n", handle); 436182732Sraj printf(" cookie\t= 0x%08x\n", (uint32_t)di->cookie); 437182732Sraj printf(" type\t\t= 0x%08x\n", di->type); 438182732Sraj 439182732Sraj if (di->type == DEV_TYP_NET) { 440182732Sraj printf(" hwaddr\t= "); 441182732Sraj for (i = 0; i < 6; i++) 442182732Sraj printf("%02x ", di->di_net.hwaddr[i]); 443182732Sraj 444182732Sraj printf("\n"); 445182732Sraj 446182732Sraj } else if (di->type & DEV_TYP_STOR) { 447182732Sraj printf(" type\t\t= %s\n", ub_stor_type(di->type)); 448182732Sraj printf(" blk size\t\t= %ld\n", di->di_stor.block_size); 449182732Sraj printf(" blk count\t\t= %ld\n", di->di_stor.block_count); 450182732Sraj } 451182732Sraj} 452182732Sraj 453182732Srajvoid 454182732Srajub_dump_si(struct sys_info *si) 455182732Sraj{ 456182732Sraj int i; 457182732Sraj 458182732Sraj printf("sys info:\n"); 459182732Sraj printf(" clkbus\t= %ld MHz\n", si->clk_bus / 1000 / 1000); 460182732Sraj printf(" clkcpu\t= %ld MHz\n", si->clk_cpu / 1000 / 1000); 461182732Sraj printf(" bar\t\t= 0x%08lx\n", si->bar); 462182732Sraj 463182732Sraj printf("---\n"); 464182732Sraj for (i = 0; i < si->mr_no; i++) { 465182732Sraj if (si->mr[i].flags == 0) 466182732Sraj break; 467182732Sraj 468182732Sraj printf(" start\t= 0x%08lx\n", si->mr[i].start); 469182732Sraj printf(" size\t= 0x%08lx\n", si->mr[i].size); 470182732Sraj printf(" type\t= %s\n", ub_mem_type(si->mr[i].flags)); 471182732Sraj printf("---\n"); 472182732Sraj } 473182732Sraj} 474182732Sraj 475176348Smarcel/**************************************** 476176348Smarcel * 477176348Smarcel * env vars 478176348Smarcel * 479176348Smarcel ****************************************/ 480176348Smarcel 481177152Sobrienchar * 482177152Sobrienub_env_get(const char *name) 483176348Smarcel{ 484176348Smarcel char *value; 485176348Smarcel 486176348Smarcel if (!syscall(API_ENV_GET, NULL, (uint32_t)name, (uint32_t)&value)) 487177108Sraj return (NULL); 488176348Smarcel 489177108Sraj return (value); 490176348Smarcel} 491176348Smarcel 492177152Sobrienvoid 493177152Sobrienub_env_set(const char *name, char *value) 494176348Smarcel{ 495177108Sraj 496176348Smarcel syscall(API_ENV_SET, NULL, (uint32_t)name, (uint32_t)value); 497176348Smarcel} 498176348Smarcel 499176348Smarcelstatic char env_name[256]; 500176348Smarcel 501177152Sobrienconst char * 502177152Sobrienub_env_enum(const char *last) 503176348Smarcel{ 504176348Smarcel const char *env, *str; 505176348Smarcel int i; 506176348Smarcel 507176348Smarcel /* 508176348Smarcel * It's OK to pass only the name piece as last (and not the whole 509176348Smarcel * 'name=val' string), since the API_ENUM_ENV call uses envmatch() 510176348Smarcel * internally, which handles such case 511176348Smarcel */ 512200691Smarcel env = NULL; 513208535Sraj if (!syscall(API_ENV_ENUM, NULL, (uint32_t)last, (uint32_t)&env)) 514177108Sraj return (NULL); 515176348Smarcel 516200691Smarcel if (env == NULL) 517176348Smarcel /* no more env. variables to enumerate */ 518177108Sraj return (NULL); 519176348Smarcel 520176348Smarcel /* next enumerated env var */ 521176348Smarcel memset(env_name, 0, 256); 522176348Smarcel for (i = 0, str = env; *str != '=' && *str != '\0';) 523176348Smarcel env_name[i++] = *str++; 524176348Smarcel 525176348Smarcel env_name[i] = '\0'; 526176348Smarcel 527177108Sraj return (env_name); 528176348Smarcel} 529