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 30233287Smarius#include <sys/types.h> 31233287Smarius 32233287Smarius#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 410235609Sgber if (type & DT_STOR_NAND) 411235609Sgber return ("NAND"); 412235609Sgber 413182732Sraj return ("Unknown"); 414182732Sraj} 415182732Sraj 416182732Srajchar * 417182732Srajub_mem_type(int flags) 418182732Sraj{ 419182732Sraj 420183599Sraj switch (flags & 0x000F) { 421182732Sraj case MR_ATTR_FLASH: 422182732Sraj return ("FLASH"); 423182732Sraj case MR_ATTR_DRAM: 424182732Sraj return ("DRAM"); 425182732Sraj case MR_ATTR_SRAM: 426182732Sraj return ("SRAM"); 427182732Sraj default: 428182732Sraj return ("Unknown"); 429182732Sraj } 430182732Sraj} 431182732Sraj 432182732Srajvoid 433182732Srajub_dump_di(int handle) 434182732Sraj{ 435182732Sraj struct device_info *di = ub_dev_get(handle); 436182732Sraj int i; 437182732Sraj 438182732Sraj printf("device info (%d):\n", handle); 439182732Sraj printf(" cookie\t= 0x%08x\n", (uint32_t)di->cookie); 440182732Sraj printf(" type\t\t= 0x%08x\n", di->type); 441182732Sraj 442182732Sraj if (di->type == DEV_TYP_NET) { 443182732Sraj printf(" hwaddr\t= "); 444182732Sraj for (i = 0; i < 6; i++) 445182732Sraj printf("%02x ", di->di_net.hwaddr[i]); 446182732Sraj 447182732Sraj printf("\n"); 448182732Sraj 449182732Sraj } else if (di->type & DEV_TYP_STOR) { 450182732Sraj printf(" type\t\t= %s\n", ub_stor_type(di->type)); 451182732Sraj printf(" blk size\t\t= %ld\n", di->di_stor.block_size); 452182732Sraj printf(" blk count\t\t= %ld\n", di->di_stor.block_count); 453182732Sraj } 454182732Sraj} 455182732Sraj 456182732Srajvoid 457182732Srajub_dump_si(struct sys_info *si) 458182732Sraj{ 459182732Sraj int i; 460182732Sraj 461182732Sraj printf("sys info:\n"); 462182732Sraj printf(" clkbus\t= %ld MHz\n", si->clk_bus / 1000 / 1000); 463182732Sraj printf(" clkcpu\t= %ld MHz\n", si->clk_cpu / 1000 / 1000); 464182732Sraj printf(" bar\t\t= 0x%08lx\n", si->bar); 465182732Sraj 466182732Sraj printf("---\n"); 467182732Sraj for (i = 0; i < si->mr_no; i++) { 468182732Sraj if (si->mr[i].flags == 0) 469182732Sraj break; 470182732Sraj 471182732Sraj printf(" start\t= 0x%08lx\n", si->mr[i].start); 472182732Sraj printf(" size\t= 0x%08lx\n", si->mr[i].size); 473182732Sraj printf(" type\t= %s\n", ub_mem_type(si->mr[i].flags)); 474182732Sraj printf("---\n"); 475182732Sraj } 476182732Sraj} 477182732Sraj 478176348Smarcel/**************************************** 479176348Smarcel * 480176348Smarcel * env vars 481176348Smarcel * 482176348Smarcel ****************************************/ 483176348Smarcel 484177152Sobrienchar * 485177152Sobrienub_env_get(const char *name) 486176348Smarcel{ 487176348Smarcel char *value; 488176348Smarcel 489176348Smarcel if (!syscall(API_ENV_GET, NULL, (uint32_t)name, (uint32_t)&value)) 490177108Sraj return (NULL); 491176348Smarcel 492177108Sraj return (value); 493176348Smarcel} 494176348Smarcel 495177152Sobrienvoid 496177152Sobrienub_env_set(const char *name, char *value) 497176348Smarcel{ 498177108Sraj 499176348Smarcel syscall(API_ENV_SET, NULL, (uint32_t)name, (uint32_t)value); 500176348Smarcel} 501176348Smarcel 502176348Smarcelstatic char env_name[256]; 503176348Smarcel 504177152Sobrienconst char * 505177152Sobrienub_env_enum(const char *last) 506176348Smarcel{ 507176348Smarcel const char *env, *str; 508176348Smarcel int i; 509176348Smarcel 510176348Smarcel /* 511176348Smarcel * It's OK to pass only the name piece as last (and not the whole 512176348Smarcel * 'name=val' string), since the API_ENUM_ENV call uses envmatch() 513176348Smarcel * internally, which handles such case 514176348Smarcel */ 515200691Smarcel env = NULL; 516208535Sraj if (!syscall(API_ENV_ENUM, NULL, (uint32_t)last, (uint32_t)&env)) 517177108Sraj return (NULL); 518176348Smarcel 519200691Smarcel if (env == NULL) 520176348Smarcel /* no more env. variables to enumerate */ 521177108Sraj return (NULL); 522176348Smarcel 523176348Smarcel /* next enumerated env var */ 524176348Smarcel memset(env_name, 0, 256); 525176348Smarcel for (i = 0, str = env; *str != '=' && *str != '\0';) 526176348Smarcel env_name[i++] = *str++; 527176348Smarcel 528176348Smarcel env_name[i] = '\0'; 529176348Smarcel 530177108Sraj return (env_name); 531176348Smarcel} 532