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: stable/11/stand/uboot/lib/glue.c 329175 2018-02-12 17:44:35Z kevans $"); 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/* 71296564Ssgalabov * Checks to see if API signature's address was given to us as a command line 72296564Ssgalabov * argument by U-Boot. 73296564Ssgalabov * 74296564Ssgalabov * returns 1/0 depending on found/not found result 75296564Ssgalabov */ 76296564Ssgalabovint 77296564Ssgalabovapi_parse_cmdline_sig(int argc, char **argv, struct api_signature **sig) 78296564Ssgalabov{ 79296564Ssgalabov unsigned long api_address; 80296564Ssgalabov int c; 81296564Ssgalabov 82296564Ssgalabov api_address = 0; 83296564Ssgalabov opterr = 0; 84296564Ssgalabov optreset = 1; 85296564Ssgalabov optind = 1; 86296564Ssgalabov 87296564Ssgalabov while ((c = getopt (argc, argv, "a:")) != -1) 88296564Ssgalabov switch (c) { 89296564Ssgalabov case 'a': 90296564Ssgalabov api_address = strtoul(optarg, NULL, 16); 91296564Ssgalabov break; 92296564Ssgalabov default: 93296564Ssgalabov break; 94296564Ssgalabov } 95296564Ssgalabov 96296564Ssgalabov if (api_address != 0) { 97296564Ssgalabov *sig = (struct api_signature *)api_address; 98296564Ssgalabov if (valid_sig(*sig)) 99296564Ssgalabov return (1); 100296564Ssgalabov } 101296564Ssgalabov 102296564Ssgalabov return (0); 103296564Ssgalabov} 104296564Ssgalabov 105296564Ssgalabov/* 106176348Smarcel * Searches for the U-Boot API signature 107176348Smarcel * 108176348Smarcel * returns 1/0 depending on found/not found result 109176348Smarcel */ 110177152Sobrienint 111177152Sobrienapi_search_sig(struct api_signature **sig) 112177152Sobrien{ 113176481Smarcel unsigned char *sp, *spend; 114176348Smarcel 115176348Smarcel if (sig == NULL) 116177108Sraj return (0); 117176348Smarcel 118176481Smarcel if (uboot_address == 0) 119176481Smarcel uboot_address = 255 * 1024 * 1024; 120176348Smarcel 121296182Ssgalabov sp = (void *)(uboot_address & API_SIG_SEARCH_MASK); 122296182Ssgalabov spend = sp + API_SIG_SEARCH_LEN - API_SIG_MAGLEN; 123296182Ssgalabov 124176481Smarcel while (sp < spend) { 125176348Smarcel if (!bcmp(sp, API_SIG_MAGIC, API_SIG_MAGLEN)) { 126176348Smarcel *sig = (struct api_signature *)sp; 127176348Smarcel if (valid_sig(*sig)) 128177108Sraj return (1); 129176348Smarcel } 130176348Smarcel sp += API_SIG_MAGLEN; 131176348Smarcel } 132176348Smarcel 133176348Smarcel *sig = NULL; 134177108Sraj return (0); 135176348Smarcel} 136176348Smarcel 137176348Smarcel/**************************************** 138176348Smarcel * 139176348Smarcel * console 140176348Smarcel * 141176348Smarcel ****************************************/ 142176348Smarcel 143177152Sobrienint 144177152Sobrienub_getc(void) 145176348Smarcel{ 146176348Smarcel int c; 147176348Smarcel 148296182Ssgalabov if (!syscall(API_GETC, NULL, &c)) 149177108Sraj return (-1); 150177108Sraj 151182732Sraj return (c); 152176348Smarcel} 153176348Smarcel 154177152Sobrienint 155177152Sobrienub_tstc(void) 156176348Smarcel{ 157176348Smarcel int t; 158176348Smarcel 159296182Ssgalabov if (!syscall(API_TSTC, NULL, &t)) 160177108Sraj return (-1); 161176348Smarcel 162182732Sraj return (t); 163176348Smarcel} 164176348Smarcel 165177152Sobrienvoid 166296182Ssgalabovub_putc(const char c) 167176348Smarcel{ 168177152Sobrien 169296182Ssgalabov syscall(API_PUTC, NULL, &c); 170176348Smarcel} 171176348Smarcel 172177152Sobrienvoid 173177152Sobrienub_puts(const char *s) 174176348Smarcel{ 175177152Sobrien 176296182Ssgalabov syscall(API_PUTS, NULL, s); 177176348Smarcel} 178176348Smarcel 179176348Smarcel/**************************************** 180176348Smarcel * 181176348Smarcel * system 182176348Smarcel * 183176348Smarcel ****************************************/ 184176348Smarcel 185177152Sobrienvoid 186177152Sobrienub_reset(void) 187176348Smarcel{ 188177152Sobrien 189176348Smarcel syscall(API_RESET, NULL); 190329175Skevans while (1); /* fallback if API_RESET failed */ 191329175Skevans __unreachable(); 192176348Smarcel} 193176348Smarcel 194183598Srajstatic struct mem_region mr[UB_MAX_MR]; 195176348Smarcelstatic struct sys_info si; 196176348Smarcel 197177152Sobrienstruct sys_info * 198177152Sobrienub_get_sys_info(void) 199176348Smarcel{ 200176348Smarcel int err = 0; 201177152Sobrien 202176348Smarcel memset(&si, 0, sizeof(struct sys_info)); 203176348Smarcel si.mr = mr; 204183598Sraj si.mr_no = UB_MAX_MR; 205176348Smarcel memset(&mr, 0, sizeof(mr)); 206177152Sobrien 207296182Ssgalabov if (!syscall(API_GET_SYS_INFO, &err, &si)) 208177108Sraj return (NULL); 209176348Smarcel 210176348Smarcel return ((err) ? NULL : &si); 211176348Smarcel} 212176348Smarcel 213176348Smarcel/**************************************** 214176348Smarcel * 215176348Smarcel * timing 216176348Smarcel * 217176348Smarcel ****************************************/ 218177108Sraj 219177152Sobrienvoid 220177152Sobrienub_udelay(unsigned long usec) 221176348Smarcel{ 222177108Sraj 223176348Smarcel syscall(API_UDELAY, NULL, &usec); 224176348Smarcel} 225176348Smarcel 226177152Sobrienunsigned long 227177152Sobrienub_get_timer(unsigned long base) 228176348Smarcel{ 229176348Smarcel unsigned long cur; 230177152Sobrien 231176348Smarcel if (!syscall(API_GET_TIMER, NULL, &cur, &base)) 232177108Sraj return (0); 233176348Smarcel 234177108Sraj return (cur); 235176348Smarcel} 236176348Smarcel 237176348Smarcel/**************************************************************************** 238176348Smarcel * 239176348Smarcel * devices 240176348Smarcel * 241183598Sraj * Devices are identified by handles: numbers 0, 1, 2, ..., UB_MAX_DEV-1 242176348Smarcel * 243176348Smarcel ***************************************************************************/ 244176348Smarcel 245183598Srajstatic struct device_info devices[UB_MAX_DEV]; 246176348Smarcel 247177152Sobrienstruct device_info * 248177152Sobrienub_dev_get(int i) 249176348Smarcel{ 250177152Sobrien 251183598Sraj return ((i < 0 || i >= UB_MAX_DEV) ? NULL : &devices[i]); 252176348Smarcel} 253176348Smarcel 254176348Smarcel/* 255176348Smarcel * Enumerates the devices: fills out device_info elements in the devices[] 256176348Smarcel * array. 257176348Smarcel * 258176348Smarcel * returns: number of devices found 259176348Smarcel */ 260177152Sobrienint 261177152Sobrienub_dev_enum(void) 262176348Smarcel{ 263176348Smarcel struct device_info *di; 264176348Smarcel int n = 0; 265176348Smarcel 266183598Sraj memset(&devices, 0, sizeof(struct device_info) * UB_MAX_DEV); 267176348Smarcel di = &devices[0]; 268176348Smarcel 269176348Smarcel if (!syscall(API_DEV_ENUM, NULL, di)) 270177108Sraj return (0); 271176348Smarcel 272176348Smarcel while (di->cookie != NULL) { 273176348Smarcel 274183598Sraj if (++n >= UB_MAX_DEV) 275176348Smarcel break; 276176348Smarcel 277176348Smarcel /* take another device_info */ 278176348Smarcel di++; 279176348Smarcel 280176348Smarcel /* pass on the previous cookie */ 281176348Smarcel di->cookie = devices[n - 1].cookie; 282176348Smarcel 283176348Smarcel if (!syscall(API_DEV_ENUM, NULL, di)) 284182732Sraj return (0); 285177108Sraj } 286176348Smarcel 287177108Sraj return (n); 288176348Smarcel} 289176348Smarcel 290176348Smarcel/* 291176348Smarcel * handle: 0-based id of the device 292176348Smarcel * 293176348Smarcel * returns: 0 when OK, err otherwise 294176348Smarcel */ 295177152Sobrienint 296177152Sobrienub_dev_open(int handle) 297176348Smarcel{ 298176348Smarcel struct device_info *di; 299176348Smarcel int err = 0; 300176348Smarcel 301183598Sraj if (handle < 0 || handle >= UB_MAX_DEV) 302177108Sraj return (API_EINVAL); 303176348Smarcel 304176348Smarcel di = &devices[handle]; 305176348Smarcel if (!syscall(API_DEV_OPEN, &err, di)) 306177108Sraj return (-1); 307176348Smarcel 308177108Sraj return (err); 309176348Smarcel} 310176348Smarcel 311177152Sobrienint 312177152Sobrienub_dev_close(int handle) 313176348Smarcel{ 314176348Smarcel struct device_info *di; 315176348Smarcel 316183598Sraj if (handle < 0 || handle >= UB_MAX_DEV) 317177108Sraj return (API_EINVAL); 318176348Smarcel 319176348Smarcel di = &devices[handle]; 320176348Smarcel if (!syscall(API_DEV_CLOSE, NULL, di)) 321177108Sraj return (-1); 322176348Smarcel 323177108Sraj return (0); 324176348Smarcel} 325176348Smarcel 326176348Smarcel/* 327176348Smarcel * Validates device for read/write, it has to: 328176348Smarcel * 329176348Smarcel * - have sane handle 330176348Smarcel * - be opened 331176348Smarcel * 332176348Smarcel * returns: 0/1 accordingly 333176348Smarcel */ 334177152Sobrienstatic int 335177152Sobriendev_valid(int handle) 336176348Smarcel{ 337177108Sraj 338183598Sraj if (handle < 0 || handle >= UB_MAX_DEV) 339177108Sraj return (0); 340176348Smarcel 341176348Smarcel if (devices[handle].state != DEV_STA_OPEN) 342177108Sraj return (0); 343176348Smarcel 344177108Sraj return (1); 345176348Smarcel} 346176348Smarcel 347177152Sobrienstatic int 348177152Sobriendev_stor_valid(int handle) 349176348Smarcel{ 350177108Sraj 351176348Smarcel if (!dev_valid(handle)) 352177108Sraj return (0); 353176348Smarcel 354176348Smarcel if (!(devices[handle].type & DEV_TYP_STOR)) 355177108Sraj return (0); 356176348Smarcel 357177108Sraj return (1); 358176348Smarcel} 359176348Smarcel 360177152Sobrienint 361183598Srajub_dev_read(int handle, void *buf, lbasize_t len, lbastart_t start, 362183598Sraj lbasize_t *rlen) 363176348Smarcel{ 364176348Smarcel struct device_info *di; 365176348Smarcel lbasize_t act_len; 366176348Smarcel int err = 0; 367176348Smarcel 368176348Smarcel if (!dev_stor_valid(handle)) 369177108Sraj return (API_ENODEV); 370176348Smarcel 371176348Smarcel di = &devices[handle]; 372176348Smarcel if (!syscall(API_DEV_READ, &err, di, buf, &len, &start, &act_len)) 373183598Sraj return (API_ESYSC); 374176348Smarcel 375183598Sraj if (!err && rlen) 376183598Sraj *rlen = act_len; 377176348Smarcel 378183598Sraj return (err); 379176348Smarcel} 380176348Smarcel 381177152Sobrienstatic int 382177152Sobriendev_net_valid(int handle) 383176348Smarcel{ 384177108Sraj 385176348Smarcel if (!dev_valid(handle)) 386177108Sraj return (0); 387176348Smarcel 388176348Smarcel if (devices[handle].type != DEV_TYP_NET) 389177108Sraj return (0); 390176348Smarcel 391177108Sraj return (1); 392176348Smarcel} 393176348Smarcel 394177152Sobrienint 395183598Srajub_dev_recv(int handle, void *buf, int len, int *rlen) 396176348Smarcel{ 397176348Smarcel struct device_info *di; 398176348Smarcel int err = 0, act_len; 399176348Smarcel 400176348Smarcel if (!dev_net_valid(handle)) 401177108Sraj return (API_ENODEV); 402176348Smarcel 403176348Smarcel di = &devices[handle]; 404176348Smarcel if (!syscall(API_DEV_READ, &err, di, buf, &len, &act_len)) 405183598Sraj return (API_ESYSC); 406176348Smarcel 407183598Sraj if (!err) 408183598Sraj *rlen = act_len; 409176348Smarcel 410183598Sraj return (err); 411176348Smarcel} 412176348Smarcel 413177152Sobrienint 414177152Sobrienub_dev_send(int handle, void *buf, int len) 415176348Smarcel{ 416176348Smarcel struct device_info *di; 417176348Smarcel int err = 0; 418176348Smarcel 419176348Smarcel if (!dev_net_valid(handle)) 420177108Sraj return (API_ENODEV); 421176348Smarcel 422176348Smarcel di = &devices[handle]; 423176348Smarcel if (!syscall(API_DEV_WRITE, &err, di, buf, &len)) 424183598Sraj return (API_ESYSC); 425176348Smarcel 426177108Sraj return (err); 427176348Smarcel} 428176348Smarcel 429185099Srajchar * 430182732Srajub_stor_type(int type) 431182732Sraj{ 432182732Sraj 433182732Sraj if (type & DT_STOR_IDE) 434182732Sraj return ("IDE"); 435182732Sraj 436182732Sraj if (type & DT_STOR_SCSI) 437182732Sraj return ("SCSI"); 438182732Sraj 439182732Sraj if (type & DT_STOR_USB) 440182732Sraj return ("USB"); 441182732Sraj 442199193Santoine if (type & DT_STOR_MMC) 443182732Sraj return ("MMC"); 444182732Sraj 445263052Sian if (type & DT_STOR_SATA) 446263052Sian return ("SATA"); 447235609Sgber 448182732Sraj return ("Unknown"); 449182732Sraj} 450182732Sraj 451182732Srajchar * 452182732Srajub_mem_type(int flags) 453182732Sraj{ 454182732Sraj 455183599Sraj switch (flags & 0x000F) { 456182732Sraj case MR_ATTR_FLASH: 457182732Sraj return ("FLASH"); 458182732Sraj case MR_ATTR_DRAM: 459182732Sraj return ("DRAM"); 460182732Sraj case MR_ATTR_SRAM: 461182732Sraj return ("SRAM"); 462182732Sraj default: 463182732Sraj return ("Unknown"); 464182732Sraj } 465182732Sraj} 466182732Sraj 467182732Srajvoid 468182732Srajub_dump_di(int handle) 469182732Sraj{ 470182732Sraj struct device_info *di = ub_dev_get(handle); 471182732Sraj int i; 472182732Sraj 473182732Sraj printf("device info (%d):\n", handle); 474307527Sgonzo printf(" cookie\t= %p\n", di->cookie); 475182732Sraj printf(" type\t\t= 0x%08x\n", di->type); 476182732Sraj 477182732Sraj if (di->type == DEV_TYP_NET) { 478182732Sraj printf(" hwaddr\t= "); 479182732Sraj for (i = 0; i < 6; i++) 480182732Sraj printf("%02x ", di->di_net.hwaddr[i]); 481182732Sraj 482182732Sraj printf("\n"); 483182732Sraj 484182732Sraj } else if (di->type & DEV_TYP_STOR) { 485182732Sraj printf(" type\t\t= %s\n", ub_stor_type(di->type)); 486182732Sraj printf(" blk size\t\t= %ld\n", di->di_stor.block_size); 487182732Sraj printf(" blk count\t\t= %ld\n", di->di_stor.block_count); 488182732Sraj } 489182732Sraj} 490182732Sraj 491182732Srajvoid 492182732Srajub_dump_si(struct sys_info *si) 493182732Sraj{ 494182732Sraj int i; 495182732Sraj 496182732Sraj printf("sys info:\n"); 497182732Sraj printf(" clkbus\t= %ld MHz\n", si->clk_bus / 1000 / 1000); 498182732Sraj printf(" clkcpu\t= %ld MHz\n", si->clk_cpu / 1000 / 1000); 499182732Sraj printf(" bar\t\t= 0x%08lx\n", si->bar); 500182732Sraj 501182732Sraj printf("---\n"); 502182732Sraj for (i = 0; i < si->mr_no; i++) { 503182732Sraj if (si->mr[i].flags == 0) 504182732Sraj break; 505182732Sraj 506182732Sraj printf(" start\t= 0x%08lx\n", si->mr[i].start); 507182732Sraj printf(" size\t= 0x%08lx\n", si->mr[i].size); 508182732Sraj printf(" type\t= %s\n", ub_mem_type(si->mr[i].flags)); 509182732Sraj printf("---\n"); 510182732Sraj } 511182732Sraj} 512182732Sraj 513176348Smarcel/**************************************** 514176348Smarcel * 515176348Smarcel * env vars 516176348Smarcel * 517176348Smarcel ****************************************/ 518176348Smarcel 519177152Sobrienchar * 520177152Sobrienub_env_get(const char *name) 521176348Smarcel{ 522176348Smarcel char *value; 523176348Smarcel 524296182Ssgalabov if (!syscall(API_ENV_GET, NULL, name, &value)) 525177108Sraj return (NULL); 526176348Smarcel 527177108Sraj return (value); 528176348Smarcel} 529176348Smarcel 530177152Sobrienvoid 531177152Sobrienub_env_set(const char *name, char *value) 532176348Smarcel{ 533177108Sraj 534296182Ssgalabov syscall(API_ENV_SET, NULL, name, value); 535176348Smarcel} 536176348Smarcel 537176348Smarcelstatic char env_name[256]; 538176348Smarcel 539177152Sobrienconst char * 540177152Sobrienub_env_enum(const char *last) 541176348Smarcel{ 542176348Smarcel const char *env, *str; 543176348Smarcel int i; 544176348Smarcel 545176348Smarcel /* 546176348Smarcel * It's OK to pass only the name piece as last (and not the whole 547176348Smarcel * 'name=val' string), since the API_ENUM_ENV call uses envmatch() 548176348Smarcel * internally, which handles such case 549176348Smarcel */ 550200691Smarcel env = NULL; 551296182Ssgalabov if (!syscall(API_ENV_ENUM, NULL, last, &env)) 552177108Sraj return (NULL); 553176348Smarcel 554284614Ssobomax if (env == NULL || last == env) 555176348Smarcel /* no more env. variables to enumerate */ 556177108Sraj return (NULL); 557176348Smarcel 558176348Smarcel /* next enumerated env var */ 559176348Smarcel memset(env_name, 0, 256); 560176348Smarcel for (i = 0, str = env; *str != '=' && *str != '\0';) 561176348Smarcel env_name[i++] = *str++; 562176348Smarcel 563176348Smarcel env_name[i] = '\0'; 564176348Smarcel 565177108Sraj return (env_name); 566176348Smarcel} 567