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: releng/10.2/sys/boot/uboot/lib/glue.c 265071 2014-04-29 00:45:42Z ian $"); 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 37176348Smarcel#ifdef DEBUG 38177152Sobrien#define debugf(fmt, args...) do { printf("%s(): ", __func__); printf(fmt,##args); } while (0) 39176348Smarcel#else 40177152Sobrien#define debugf(fmt, args...) 41176348Smarcel#endif 42176348Smarcel 43176481Smarcel/* Some random address used by U-Boot. */ 44182732Srajextern long uboot_address; 45176348Smarcel 46177152Sobrienstatic int 47177152Sobrienvalid_sig(struct api_signature *sig) 48176348Smarcel{ 49176348Smarcel uint32_t checksum; 50176348Smarcel struct api_signature s; 51176348Smarcel 52176348Smarcel if (sig == NULL) 53177108Sraj return (0); 54176348Smarcel /* 55176348Smarcel * Clear the checksum field (in the local copy) so as to calculate the 56176348Smarcel * CRC with the same initial contents as at the time when the sig was 57176348Smarcel * produced 58176348Smarcel */ 59176348Smarcel s = *sig; 60176348Smarcel s.checksum = 0; 61176348Smarcel 62176348Smarcel checksum = crc32((void *)&s, sizeof(struct api_signature)); 63176348Smarcel 64176348Smarcel if (checksum != sig->checksum) 65177108Sraj return (0); 66176348Smarcel 67177108Sraj return (1); 68176348Smarcel} 69176348Smarcel 70176348Smarcel/* 71176348Smarcel * Searches for the U-Boot API signature 72176348Smarcel * 73176348Smarcel * returns 1/0 depending on found/not found result 74176348Smarcel */ 75177152Sobrienint 76177152Sobrienapi_search_sig(struct api_signature **sig) 77177152Sobrien{ 78176481Smarcel unsigned char *sp, *spend; 79176348Smarcel 80176348Smarcel if (sig == NULL) 81177108Sraj return (0); 82176348Smarcel 83176481Smarcel if (uboot_address == 0) 84176481Smarcel uboot_address = 255 * 1024 * 1024; 85176348Smarcel 86176481Smarcel sp = (void *)(uboot_address & ~0x000fffff); 87183878Sraj spend = sp + 0x00300000 - API_SIG_MAGLEN; 88176481Smarcel while (sp < spend) { 89176348Smarcel if (!bcmp(sp, API_SIG_MAGIC, API_SIG_MAGLEN)) { 90176348Smarcel *sig = (struct api_signature *)sp; 91176348Smarcel if (valid_sig(*sig)) 92177108Sraj return (1); 93176348Smarcel } 94176348Smarcel sp += API_SIG_MAGLEN; 95176348Smarcel } 96176348Smarcel 97176348Smarcel *sig = NULL; 98177108Sraj return (0); 99176348Smarcel} 100176348Smarcel 101176348Smarcel/**************************************** 102176348Smarcel * 103176348Smarcel * console 104176348Smarcel * 105176348Smarcel ****************************************/ 106176348Smarcel 107177152Sobrienint 108177152Sobrienub_getc(void) 109176348Smarcel{ 110176348Smarcel int c; 111176348Smarcel 112176348Smarcel if (!syscall(API_GETC, NULL, (uint32_t)&c)) 113177108Sraj return (-1); 114177108Sraj 115182732Sraj return (c); 116176348Smarcel} 117176348Smarcel 118177152Sobrienint 119177152Sobrienub_tstc(void) 120176348Smarcel{ 121176348Smarcel int t; 122176348Smarcel 123176348Smarcel if (!syscall(API_TSTC, NULL, (uint32_t)&t)) 124177108Sraj return (-1); 125176348Smarcel 126182732Sraj return (t); 127176348Smarcel} 128176348Smarcel 129177152Sobrienvoid 130177152Sobrienub_putc(char c) 131176348Smarcel{ 132177152Sobrien 133176348Smarcel syscall(API_PUTC, NULL, (uint32_t)&c); 134176348Smarcel} 135176348Smarcel 136177152Sobrienvoid 137177152Sobrienub_puts(const char *s) 138176348Smarcel{ 139177152Sobrien 140176348Smarcel syscall(API_PUTS, NULL, (uint32_t)s); 141176348Smarcel} 142176348Smarcel 143176348Smarcel/**************************************** 144176348Smarcel * 145176348Smarcel * system 146176348Smarcel * 147176348Smarcel ****************************************/ 148176348Smarcel 149177152Sobrienvoid 150177152Sobrienub_reset(void) 151176348Smarcel{ 152177152Sobrien 153176348Smarcel syscall(API_RESET, NULL); 154176348Smarcel} 155176348Smarcel 156183598Srajstatic struct mem_region mr[UB_MAX_MR]; 157176348Smarcelstatic struct sys_info si; 158176348Smarcel 159177152Sobrienstruct sys_info * 160177152Sobrienub_get_sys_info(void) 161176348Smarcel{ 162176348Smarcel int err = 0; 163177152Sobrien 164176348Smarcel memset(&si, 0, sizeof(struct sys_info)); 165176348Smarcel si.mr = mr; 166183598Sraj si.mr_no = UB_MAX_MR; 167176348Smarcel memset(&mr, 0, sizeof(mr)); 168177152Sobrien 169176348Smarcel if (!syscall(API_GET_SYS_INFO, &err, (u_int32_t)&si)) 170177108Sraj return (NULL); 171176348Smarcel 172176348Smarcel return ((err) ? NULL : &si); 173176348Smarcel} 174176348Smarcel 175176348Smarcel/**************************************** 176176348Smarcel * 177176348Smarcel * timing 178176348Smarcel * 179176348Smarcel ****************************************/ 180177108Sraj 181177152Sobrienvoid 182177152Sobrienub_udelay(unsigned long usec) 183176348Smarcel{ 184177108Sraj 185176348Smarcel syscall(API_UDELAY, NULL, &usec); 186176348Smarcel} 187176348Smarcel 188177152Sobrienunsigned long 189177152Sobrienub_get_timer(unsigned long base) 190176348Smarcel{ 191176348Smarcel unsigned long cur; 192177152Sobrien 193176348Smarcel if (!syscall(API_GET_TIMER, NULL, &cur, &base)) 194177108Sraj return (0); 195176348Smarcel 196177108Sraj return (cur); 197176348Smarcel} 198176348Smarcel 199176348Smarcel/**************************************************************************** 200176348Smarcel * 201176348Smarcel * devices 202176348Smarcel * 203183598Sraj * Devices are identified by handles: numbers 0, 1, 2, ..., UB_MAX_DEV-1 204176348Smarcel * 205176348Smarcel ***************************************************************************/ 206176348Smarcel 207183598Srajstatic struct device_info devices[UB_MAX_DEV]; 208176348Smarcel 209177152Sobrienstruct device_info * 210177152Sobrienub_dev_get(int i) 211176348Smarcel{ 212177152Sobrien 213183598Sraj return ((i < 0 || i >= UB_MAX_DEV) ? NULL : &devices[i]); 214176348Smarcel} 215176348Smarcel 216176348Smarcel/* 217176348Smarcel * Enumerates the devices: fills out device_info elements in the devices[] 218176348Smarcel * array. 219176348Smarcel * 220176348Smarcel * returns: number of devices found 221176348Smarcel */ 222177152Sobrienint 223177152Sobrienub_dev_enum(void) 224176348Smarcel{ 225176348Smarcel struct device_info *di; 226176348Smarcel int n = 0; 227176348Smarcel 228183598Sraj memset(&devices, 0, sizeof(struct device_info) * UB_MAX_DEV); 229176348Smarcel di = &devices[0]; 230176348Smarcel 231176348Smarcel if (!syscall(API_DEV_ENUM, NULL, di)) 232177108Sraj return (0); 233176348Smarcel 234176348Smarcel while (di->cookie != NULL) { 235176348Smarcel 236183598Sraj if (++n >= UB_MAX_DEV) 237176348Smarcel break; 238176348Smarcel 239176348Smarcel /* take another device_info */ 240176348Smarcel di++; 241176348Smarcel 242176348Smarcel /* pass on the previous cookie */ 243176348Smarcel di->cookie = devices[n - 1].cookie; 244176348Smarcel 245176348Smarcel if (!syscall(API_DEV_ENUM, NULL, di)) 246182732Sraj return (0); 247177108Sraj } 248176348Smarcel 249177108Sraj return (n); 250176348Smarcel} 251176348Smarcel 252176348Smarcel/* 253176348Smarcel * handle: 0-based id of the device 254176348Smarcel * 255176348Smarcel * returns: 0 when OK, err otherwise 256176348Smarcel */ 257177152Sobrienint 258177152Sobrienub_dev_open(int handle) 259176348Smarcel{ 260176348Smarcel struct device_info *di; 261176348Smarcel int err = 0; 262176348Smarcel 263183598Sraj if (handle < 0 || handle >= UB_MAX_DEV) 264177108Sraj return (API_EINVAL); 265176348Smarcel 266176348Smarcel di = &devices[handle]; 267176348Smarcel if (!syscall(API_DEV_OPEN, &err, di)) 268177108Sraj return (-1); 269176348Smarcel 270177108Sraj return (err); 271176348Smarcel} 272176348Smarcel 273177152Sobrienint 274177152Sobrienub_dev_close(int handle) 275176348Smarcel{ 276176348Smarcel struct device_info *di; 277176348Smarcel 278183598Sraj if (handle < 0 || handle >= UB_MAX_DEV) 279177108Sraj return (API_EINVAL); 280176348Smarcel 281176348Smarcel di = &devices[handle]; 282176348Smarcel if (!syscall(API_DEV_CLOSE, NULL, di)) 283177108Sraj return (-1); 284176348Smarcel 285177108Sraj return (0); 286176348Smarcel} 287176348Smarcel 288176348Smarcel/* 289176348Smarcel * Validates device for read/write, it has to: 290176348Smarcel * 291176348Smarcel * - have sane handle 292176348Smarcel * - be opened 293176348Smarcel * 294176348Smarcel * returns: 0/1 accordingly 295176348Smarcel */ 296177152Sobrienstatic int 297177152Sobriendev_valid(int handle) 298176348Smarcel{ 299177108Sraj 300183598Sraj if (handle < 0 || handle >= UB_MAX_DEV) 301177108Sraj return (0); 302176348Smarcel 303176348Smarcel if (devices[handle].state != DEV_STA_OPEN) 304177108Sraj return (0); 305176348Smarcel 306177108Sraj return (1); 307176348Smarcel} 308176348Smarcel 309177152Sobrienstatic int 310177152Sobriendev_stor_valid(int handle) 311176348Smarcel{ 312177108Sraj 313176348Smarcel if (!dev_valid(handle)) 314177108Sraj return (0); 315176348Smarcel 316176348Smarcel if (!(devices[handle].type & DEV_TYP_STOR)) 317177108Sraj return (0); 318176348Smarcel 319177108Sraj return (1); 320176348Smarcel} 321176348Smarcel 322177152Sobrienint 323183598Srajub_dev_read(int handle, void *buf, lbasize_t len, lbastart_t start, 324183598Sraj lbasize_t *rlen) 325176348Smarcel{ 326176348Smarcel struct device_info *di; 327176348Smarcel lbasize_t act_len; 328176348Smarcel int err = 0; 329176348Smarcel 330176348Smarcel if (!dev_stor_valid(handle)) 331177108Sraj return (API_ENODEV); 332176348Smarcel 333176348Smarcel di = &devices[handle]; 334176348Smarcel if (!syscall(API_DEV_READ, &err, di, buf, &len, &start, &act_len)) 335183598Sraj return (API_ESYSC); 336176348Smarcel 337183598Sraj if (!err && rlen) 338183598Sraj *rlen = act_len; 339176348Smarcel 340183598Sraj return (err); 341176348Smarcel} 342176348Smarcel 343177152Sobrienstatic int 344177152Sobriendev_net_valid(int handle) 345176348Smarcel{ 346177108Sraj 347176348Smarcel if (!dev_valid(handle)) 348177108Sraj return (0); 349176348Smarcel 350176348Smarcel if (devices[handle].type != DEV_TYP_NET) 351177108Sraj return (0); 352176348Smarcel 353177108Sraj return (1); 354176348Smarcel} 355176348Smarcel 356177152Sobrienint 357183598Srajub_dev_recv(int handle, void *buf, int len, int *rlen) 358176348Smarcel{ 359176348Smarcel struct device_info *di; 360176348Smarcel int err = 0, act_len; 361176348Smarcel 362176348Smarcel if (!dev_net_valid(handle)) 363177108Sraj return (API_ENODEV); 364176348Smarcel 365176348Smarcel di = &devices[handle]; 366176348Smarcel if (!syscall(API_DEV_READ, &err, di, buf, &len, &act_len)) 367183598Sraj return (API_ESYSC); 368176348Smarcel 369183598Sraj if (!err) 370183598Sraj *rlen = act_len; 371176348Smarcel 372183598Sraj return (err); 373176348Smarcel} 374176348Smarcel 375177152Sobrienint 376177152Sobrienub_dev_send(int handle, void *buf, int len) 377176348Smarcel{ 378176348Smarcel struct device_info *di; 379176348Smarcel int err = 0; 380176348Smarcel 381176348Smarcel if (!dev_net_valid(handle)) 382177108Sraj return (API_ENODEV); 383176348Smarcel 384176348Smarcel di = &devices[handle]; 385176348Smarcel if (!syscall(API_DEV_WRITE, &err, di, buf, &len)) 386183598Sraj return (API_ESYSC); 387176348Smarcel 388177108Sraj return (err); 389176348Smarcel} 390176348Smarcel 391185099Srajchar * 392182732Srajub_stor_type(int type) 393182732Sraj{ 394182732Sraj 395182732Sraj if (type & DT_STOR_IDE) 396182732Sraj return ("IDE"); 397182732Sraj 398182732Sraj if (type & DT_STOR_SCSI) 399182732Sraj return ("SCSI"); 400182732Sraj 401182732Sraj if (type & DT_STOR_USB) 402182732Sraj return ("USB"); 403182732Sraj 404199193Santoine if (type & DT_STOR_MMC) 405182732Sraj return ("MMC"); 406182732Sraj 407265071Sian if (type & DT_STOR_SATA) 408265071Sian return ("SATA"); 409235609Sgber 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