1*d4abc757SPeter Tyser /* 2*d4abc757SPeter Tyser * (C) Copyright 2007-2008 Semihalf, Rafal Jaworowski <raj@semihalf.com> 3*d4abc757SPeter Tyser * 4*d4abc757SPeter Tyser * See file CREDITS for list of people who contributed to this 5*d4abc757SPeter Tyser * project. 6*d4abc757SPeter Tyser * 7*d4abc757SPeter Tyser * This program is free software; you can redistribute it and/or 8*d4abc757SPeter Tyser * modify it under the terms of the GNU General Public License as 9*d4abc757SPeter Tyser * published by the Free Software Foundation; either version 2 of 10*d4abc757SPeter Tyser * the License, or (at your option) any later version. 11*d4abc757SPeter Tyser * 12*d4abc757SPeter Tyser * This program is distributed in the hope that it will be useful, 13*d4abc757SPeter Tyser * but WITHOUT ANY WARRANTY; without even the implied warranty of 14*d4abc757SPeter Tyser * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15*d4abc757SPeter Tyser * GNU General Public License for more details. 16*d4abc757SPeter Tyser * 17*d4abc757SPeter Tyser * You should have received a copy of the GNU General Public License 18*d4abc757SPeter Tyser * along with this program; if not, write to the Free Software 19*d4abc757SPeter Tyser * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 20*d4abc757SPeter Tyser * MA 02111-1307 USA 21*d4abc757SPeter Tyser * 22*d4abc757SPeter Tyser */ 23*d4abc757SPeter Tyser 24*d4abc757SPeter Tyser #include <common.h> 25*d4abc757SPeter Tyser #include <linux/types.h> 26*d4abc757SPeter Tyser #include <api_public.h> 27*d4abc757SPeter Tyser 28*d4abc757SPeter Tyser #include "glue.h" 29*d4abc757SPeter Tyser 30*d4abc757SPeter Tyser static int valid_sig(struct api_signature *sig) 31*d4abc757SPeter Tyser { 32*d4abc757SPeter Tyser uint32_t checksum; 33*d4abc757SPeter Tyser struct api_signature s; 34*d4abc757SPeter Tyser 35*d4abc757SPeter Tyser if (sig == NULL) 36*d4abc757SPeter Tyser return 0; 37*d4abc757SPeter Tyser /* 38*d4abc757SPeter Tyser * Clear the checksum field (in the local copy) so as to calculate the 39*d4abc757SPeter Tyser * CRC with the same initial contents as at the time when the sig was 40*d4abc757SPeter Tyser * produced 41*d4abc757SPeter Tyser */ 42*d4abc757SPeter Tyser s = *sig; 43*d4abc757SPeter Tyser s.checksum = 0; 44*d4abc757SPeter Tyser 45*d4abc757SPeter Tyser checksum = crc32(0, (unsigned char *)&s, sizeof(struct api_signature)); 46*d4abc757SPeter Tyser 47*d4abc757SPeter Tyser if (checksum != sig->checksum) 48*d4abc757SPeter Tyser return 0; 49*d4abc757SPeter Tyser 50*d4abc757SPeter Tyser return 1; 51*d4abc757SPeter Tyser } 52*d4abc757SPeter Tyser 53*d4abc757SPeter Tyser /* 54*d4abc757SPeter Tyser * Searches for the U-Boot API signature 55*d4abc757SPeter Tyser * 56*d4abc757SPeter Tyser * returns 1/0 depending on found/not found result 57*d4abc757SPeter Tyser */ 58*d4abc757SPeter Tyser int api_search_sig(struct api_signature **sig) 59*d4abc757SPeter Tyser { 60*d4abc757SPeter Tyser unsigned char *sp; 61*d4abc757SPeter Tyser uint32_t search_start = 0; 62*d4abc757SPeter Tyser uint32_t search_end = 0; 63*d4abc757SPeter Tyser 64*d4abc757SPeter Tyser if (sig == NULL) 65*d4abc757SPeter Tyser return 0; 66*d4abc757SPeter Tyser 67*d4abc757SPeter Tyser if (search_hint == 0) 68*d4abc757SPeter Tyser search_hint = 255 * 1024 * 1024; 69*d4abc757SPeter Tyser 70*d4abc757SPeter Tyser search_start = search_hint & ~0x000fffff; 71*d4abc757SPeter Tyser search_end = search_start + API_SEARCH_LEN - API_SIG_MAGLEN; 72*d4abc757SPeter Tyser 73*d4abc757SPeter Tyser sp = (unsigned char *)search_start; 74*d4abc757SPeter Tyser while ((sp + API_SIG_MAGLEN) < (unsigned char *)search_end) { 75*d4abc757SPeter Tyser if (!memcmp(sp, API_SIG_MAGIC, API_SIG_MAGLEN)) { 76*d4abc757SPeter Tyser *sig = (struct api_signature *)sp; 77*d4abc757SPeter Tyser if (valid_sig(*sig)) 78*d4abc757SPeter Tyser return 1; 79*d4abc757SPeter Tyser } 80*d4abc757SPeter Tyser sp += API_SIG_MAGLEN; 81*d4abc757SPeter Tyser } 82*d4abc757SPeter Tyser 83*d4abc757SPeter Tyser *sig = NULL; 84*d4abc757SPeter Tyser return 0; 85*d4abc757SPeter Tyser } 86*d4abc757SPeter Tyser 87*d4abc757SPeter Tyser /**************************************** 88*d4abc757SPeter Tyser * 89*d4abc757SPeter Tyser * console 90*d4abc757SPeter Tyser * 91*d4abc757SPeter Tyser ****************************************/ 92*d4abc757SPeter Tyser 93*d4abc757SPeter Tyser int ub_getc(void) 94*d4abc757SPeter Tyser { 95*d4abc757SPeter Tyser int c; 96*d4abc757SPeter Tyser 97*d4abc757SPeter Tyser if (!syscall(API_GETC, NULL, (uint32_t)&c)) 98*d4abc757SPeter Tyser return -1; 99*d4abc757SPeter Tyser 100*d4abc757SPeter Tyser return c; 101*d4abc757SPeter Tyser } 102*d4abc757SPeter Tyser 103*d4abc757SPeter Tyser int ub_tstc(void) 104*d4abc757SPeter Tyser { 105*d4abc757SPeter Tyser int t; 106*d4abc757SPeter Tyser 107*d4abc757SPeter Tyser if (!syscall(API_TSTC, NULL, (uint32_t)&t)) 108*d4abc757SPeter Tyser return -1; 109*d4abc757SPeter Tyser 110*d4abc757SPeter Tyser return t; 111*d4abc757SPeter Tyser } 112*d4abc757SPeter Tyser 113*d4abc757SPeter Tyser void ub_putc(char c) 114*d4abc757SPeter Tyser { 115*d4abc757SPeter Tyser syscall(API_PUTC, NULL, (uint32_t)&c); 116*d4abc757SPeter Tyser } 117*d4abc757SPeter Tyser 118*d4abc757SPeter Tyser void ub_puts(const char *s) 119*d4abc757SPeter Tyser { 120*d4abc757SPeter Tyser syscall(API_PUTS, NULL, (uint32_t)s); 121*d4abc757SPeter Tyser } 122*d4abc757SPeter Tyser 123*d4abc757SPeter Tyser /**************************************** 124*d4abc757SPeter Tyser * 125*d4abc757SPeter Tyser * system 126*d4abc757SPeter Tyser * 127*d4abc757SPeter Tyser ****************************************/ 128*d4abc757SPeter Tyser 129*d4abc757SPeter Tyser void ub_reset(void) 130*d4abc757SPeter Tyser { 131*d4abc757SPeter Tyser syscall(API_RESET, NULL); 132*d4abc757SPeter Tyser } 133*d4abc757SPeter Tyser 134*d4abc757SPeter Tyser static struct mem_region mr[UB_MAX_MR]; 135*d4abc757SPeter Tyser static struct sys_info si; 136*d4abc757SPeter Tyser 137*d4abc757SPeter Tyser struct sys_info * ub_get_sys_info(void) 138*d4abc757SPeter Tyser { 139*d4abc757SPeter Tyser int err = 0; 140*d4abc757SPeter Tyser 141*d4abc757SPeter Tyser memset(&si, 0, sizeof(struct sys_info)); 142*d4abc757SPeter Tyser si.mr = mr; 143*d4abc757SPeter Tyser si.mr_no = UB_MAX_MR; 144*d4abc757SPeter Tyser memset(&mr, 0, sizeof(mr)); 145*d4abc757SPeter Tyser 146*d4abc757SPeter Tyser if (!syscall(API_GET_SYS_INFO, &err, (u_int32_t)&si)) 147*d4abc757SPeter Tyser return NULL; 148*d4abc757SPeter Tyser 149*d4abc757SPeter Tyser return ((err) ? NULL : &si); 150*d4abc757SPeter Tyser } 151*d4abc757SPeter Tyser 152*d4abc757SPeter Tyser /**************************************** 153*d4abc757SPeter Tyser * 154*d4abc757SPeter Tyser * timing 155*d4abc757SPeter Tyser * 156*d4abc757SPeter Tyser ****************************************/ 157*d4abc757SPeter Tyser 158*d4abc757SPeter Tyser void ub_udelay(unsigned long usec) 159*d4abc757SPeter Tyser { 160*d4abc757SPeter Tyser syscall(API_UDELAY, NULL, &usec); 161*d4abc757SPeter Tyser } 162*d4abc757SPeter Tyser 163*d4abc757SPeter Tyser unsigned long ub_get_timer(unsigned long base) 164*d4abc757SPeter Tyser { 165*d4abc757SPeter Tyser unsigned long cur; 166*d4abc757SPeter Tyser 167*d4abc757SPeter Tyser if (!syscall(API_GET_TIMER, NULL, &cur, &base)) 168*d4abc757SPeter Tyser return 0; 169*d4abc757SPeter Tyser 170*d4abc757SPeter Tyser return cur; 171*d4abc757SPeter Tyser } 172*d4abc757SPeter Tyser 173*d4abc757SPeter Tyser 174*d4abc757SPeter Tyser /**************************************************************************** 175*d4abc757SPeter Tyser * 176*d4abc757SPeter Tyser * devices 177*d4abc757SPeter Tyser * 178*d4abc757SPeter Tyser * Devices are identified by handles: numbers 0, 1, 2, ..., UB_MAX_DEV-1 179*d4abc757SPeter Tyser * 180*d4abc757SPeter Tyser ***************************************************************************/ 181*d4abc757SPeter Tyser 182*d4abc757SPeter Tyser static struct device_info devices[UB_MAX_DEV]; 183*d4abc757SPeter Tyser 184*d4abc757SPeter Tyser struct device_info * ub_dev_get(int i) 185*d4abc757SPeter Tyser { 186*d4abc757SPeter Tyser return ((i < 0 || i >= UB_MAX_DEV) ? NULL : &devices[i]); 187*d4abc757SPeter Tyser } 188*d4abc757SPeter Tyser 189*d4abc757SPeter Tyser /* 190*d4abc757SPeter Tyser * Enumerates the devices: fills out device_info elements in the devices[] 191*d4abc757SPeter Tyser * array. 192*d4abc757SPeter Tyser * 193*d4abc757SPeter Tyser * returns: number of devices found 194*d4abc757SPeter Tyser */ 195*d4abc757SPeter Tyser int ub_dev_enum(void) 196*d4abc757SPeter Tyser { 197*d4abc757SPeter Tyser struct device_info *di; 198*d4abc757SPeter Tyser int n = 0; 199*d4abc757SPeter Tyser 200*d4abc757SPeter Tyser memset(&devices, 0, sizeof(struct device_info) * UB_MAX_DEV); 201*d4abc757SPeter Tyser di = &devices[0]; 202*d4abc757SPeter Tyser 203*d4abc757SPeter Tyser if (!syscall(API_DEV_ENUM, NULL, di)) 204*d4abc757SPeter Tyser return 0; 205*d4abc757SPeter Tyser 206*d4abc757SPeter Tyser while (di->cookie != NULL) { 207*d4abc757SPeter Tyser 208*d4abc757SPeter Tyser if (++n >= UB_MAX_DEV) 209*d4abc757SPeter Tyser break; 210*d4abc757SPeter Tyser 211*d4abc757SPeter Tyser /* take another device_info */ 212*d4abc757SPeter Tyser di++; 213*d4abc757SPeter Tyser 214*d4abc757SPeter Tyser /* pass on the previous cookie */ 215*d4abc757SPeter Tyser di->cookie = devices[n - 1].cookie; 216*d4abc757SPeter Tyser 217*d4abc757SPeter Tyser if (!syscall(API_DEV_ENUM, NULL, di)) 218*d4abc757SPeter Tyser return 0; 219*d4abc757SPeter Tyser } 220*d4abc757SPeter Tyser 221*d4abc757SPeter Tyser return n; 222*d4abc757SPeter Tyser } 223*d4abc757SPeter Tyser 224*d4abc757SPeter Tyser /* 225*d4abc757SPeter Tyser * handle: 0-based id of the device 226*d4abc757SPeter Tyser * 227*d4abc757SPeter Tyser * returns: 0 when OK, err otherwise 228*d4abc757SPeter Tyser */ 229*d4abc757SPeter Tyser int ub_dev_open(int handle) 230*d4abc757SPeter Tyser { 231*d4abc757SPeter Tyser struct device_info *di; 232*d4abc757SPeter Tyser int err = 0; 233*d4abc757SPeter Tyser 234*d4abc757SPeter Tyser if (handle < 0 || handle >= UB_MAX_DEV) 235*d4abc757SPeter Tyser return API_EINVAL; 236*d4abc757SPeter Tyser 237*d4abc757SPeter Tyser di = &devices[handle]; 238*d4abc757SPeter Tyser 239*d4abc757SPeter Tyser if (!syscall(API_DEV_OPEN, &err, di)) 240*d4abc757SPeter Tyser return -1; 241*d4abc757SPeter Tyser 242*d4abc757SPeter Tyser return err; 243*d4abc757SPeter Tyser } 244*d4abc757SPeter Tyser 245*d4abc757SPeter Tyser int ub_dev_close(int handle) 246*d4abc757SPeter Tyser { 247*d4abc757SPeter Tyser struct device_info *di; 248*d4abc757SPeter Tyser 249*d4abc757SPeter Tyser if (handle < 0 || handle >= UB_MAX_DEV) 250*d4abc757SPeter Tyser return API_EINVAL; 251*d4abc757SPeter Tyser 252*d4abc757SPeter Tyser di = &devices[handle]; 253*d4abc757SPeter Tyser if (!syscall(API_DEV_CLOSE, NULL, di)) 254*d4abc757SPeter Tyser return -1; 255*d4abc757SPeter Tyser 256*d4abc757SPeter Tyser return 0; 257*d4abc757SPeter Tyser } 258*d4abc757SPeter Tyser 259*d4abc757SPeter Tyser /* 260*d4abc757SPeter Tyser * 261*d4abc757SPeter Tyser * Validates device for read/write, it has to: 262*d4abc757SPeter Tyser * 263*d4abc757SPeter Tyser * - have sane handle 264*d4abc757SPeter Tyser * - be opened 265*d4abc757SPeter Tyser * 266*d4abc757SPeter Tyser * returns: 0/1 accordingly 267*d4abc757SPeter Tyser */ 268*d4abc757SPeter Tyser static int dev_valid(int handle) 269*d4abc757SPeter Tyser { 270*d4abc757SPeter Tyser if (handle < 0 || handle >= UB_MAX_DEV) 271*d4abc757SPeter Tyser return 0; 272*d4abc757SPeter Tyser 273*d4abc757SPeter Tyser if (devices[handle].state != DEV_STA_OPEN) 274*d4abc757SPeter Tyser return 0; 275*d4abc757SPeter Tyser 276*d4abc757SPeter Tyser return 1; 277*d4abc757SPeter Tyser } 278*d4abc757SPeter Tyser 279*d4abc757SPeter Tyser static int dev_stor_valid(int handle) 280*d4abc757SPeter Tyser { 281*d4abc757SPeter Tyser if (!dev_valid(handle)) 282*d4abc757SPeter Tyser return 0; 283*d4abc757SPeter Tyser 284*d4abc757SPeter Tyser if (!(devices[handle].type & DEV_TYP_STOR)) 285*d4abc757SPeter Tyser return 0; 286*d4abc757SPeter Tyser 287*d4abc757SPeter Tyser return 1; 288*d4abc757SPeter Tyser } 289*d4abc757SPeter Tyser 290*d4abc757SPeter Tyser int ub_dev_read(int handle, void *buf, lbasize_t len, lbastart_t start, 291*d4abc757SPeter Tyser lbasize_t *rlen) 292*d4abc757SPeter Tyser { 293*d4abc757SPeter Tyser struct device_info *di; 294*d4abc757SPeter Tyser lbasize_t act_len; 295*d4abc757SPeter Tyser int err = 0; 296*d4abc757SPeter Tyser 297*d4abc757SPeter Tyser if (!dev_stor_valid(handle)) 298*d4abc757SPeter Tyser return API_ENODEV; 299*d4abc757SPeter Tyser 300*d4abc757SPeter Tyser di = &devices[handle]; 301*d4abc757SPeter Tyser if (!syscall(API_DEV_READ, &err, di, buf, &len, &start, &act_len)) 302*d4abc757SPeter Tyser return API_ESYSC; 303*d4abc757SPeter Tyser 304*d4abc757SPeter Tyser if (!err && rlen) 305*d4abc757SPeter Tyser *rlen = act_len; 306*d4abc757SPeter Tyser 307*d4abc757SPeter Tyser return err; 308*d4abc757SPeter Tyser } 309*d4abc757SPeter Tyser 310*d4abc757SPeter Tyser static int dev_net_valid(int handle) 311*d4abc757SPeter Tyser { 312*d4abc757SPeter Tyser if (!dev_valid(handle)) 313*d4abc757SPeter Tyser return 0; 314*d4abc757SPeter Tyser 315*d4abc757SPeter Tyser if (devices[handle].type != DEV_TYP_NET) 316*d4abc757SPeter Tyser return 0; 317*d4abc757SPeter Tyser 318*d4abc757SPeter Tyser return 1; 319*d4abc757SPeter Tyser } 320*d4abc757SPeter Tyser 321*d4abc757SPeter Tyser int ub_dev_recv(int handle, void *buf, int len, int *rlen) 322*d4abc757SPeter Tyser { 323*d4abc757SPeter Tyser struct device_info *di; 324*d4abc757SPeter Tyser int err = 0, act_len; 325*d4abc757SPeter Tyser 326*d4abc757SPeter Tyser if (!dev_net_valid(handle)) 327*d4abc757SPeter Tyser return API_ENODEV; 328*d4abc757SPeter Tyser 329*d4abc757SPeter Tyser di = &devices[handle]; 330*d4abc757SPeter Tyser if (!syscall(API_DEV_READ, &err, di, buf, &len, &act_len)) 331*d4abc757SPeter Tyser return API_ESYSC; 332*d4abc757SPeter Tyser 333*d4abc757SPeter Tyser if (!err && rlen) 334*d4abc757SPeter Tyser *rlen = act_len; 335*d4abc757SPeter Tyser 336*d4abc757SPeter Tyser return (err); 337*d4abc757SPeter Tyser } 338*d4abc757SPeter Tyser 339*d4abc757SPeter Tyser int ub_dev_send(int handle, void *buf, int len) 340*d4abc757SPeter Tyser { 341*d4abc757SPeter Tyser struct device_info *di; 342*d4abc757SPeter Tyser int err = 0; 343*d4abc757SPeter Tyser 344*d4abc757SPeter Tyser if (!dev_net_valid(handle)) 345*d4abc757SPeter Tyser return API_ENODEV; 346*d4abc757SPeter Tyser 347*d4abc757SPeter Tyser di = &devices[handle]; 348*d4abc757SPeter Tyser if (!syscall(API_DEV_WRITE, &err, di, buf, &len)) 349*d4abc757SPeter Tyser return API_ESYSC; 350*d4abc757SPeter Tyser 351*d4abc757SPeter Tyser return err; 352*d4abc757SPeter Tyser } 353*d4abc757SPeter Tyser 354*d4abc757SPeter Tyser /**************************************** 355*d4abc757SPeter Tyser * 356*d4abc757SPeter Tyser * env vars 357*d4abc757SPeter Tyser * 358*d4abc757SPeter Tyser ****************************************/ 359*d4abc757SPeter Tyser 360*d4abc757SPeter Tyser char * ub_env_get(const char *name) 361*d4abc757SPeter Tyser { 362*d4abc757SPeter Tyser char *value; 363*d4abc757SPeter Tyser 364*d4abc757SPeter Tyser if (!syscall(API_ENV_GET, NULL, (uint32_t)name, (uint32_t)&value)) 365*d4abc757SPeter Tyser return NULL; 366*d4abc757SPeter Tyser 367*d4abc757SPeter Tyser return value; 368*d4abc757SPeter Tyser } 369*d4abc757SPeter Tyser 370*d4abc757SPeter Tyser void ub_env_set(const char *name, char *value) 371*d4abc757SPeter Tyser { 372*d4abc757SPeter Tyser syscall(API_ENV_SET, NULL, (uint32_t)name, (uint32_t)value); 373*d4abc757SPeter Tyser } 374*d4abc757SPeter Tyser 375*d4abc757SPeter Tyser static char env_name[256]; 376*d4abc757SPeter Tyser 377*d4abc757SPeter Tyser const char * ub_env_enum(const char *last) 378*d4abc757SPeter Tyser { 379*d4abc757SPeter Tyser const char *env, *str; 380*d4abc757SPeter Tyser int i; 381*d4abc757SPeter Tyser 382*d4abc757SPeter Tyser env = NULL; 383*d4abc757SPeter Tyser 384*d4abc757SPeter Tyser /* 385*d4abc757SPeter Tyser * It's OK to pass only the name piece as last (and not the whole 386*d4abc757SPeter Tyser * 'name=val' string), since the API_ENUM_ENV call uses envmatch() 387*d4abc757SPeter Tyser * internally, which handles such case 388*d4abc757SPeter Tyser */ 389*d4abc757SPeter Tyser if (!syscall(API_ENV_ENUM, NULL, (uint32_t)last, (uint32_t)&env)) 390*d4abc757SPeter Tyser return NULL; 391*d4abc757SPeter Tyser 392*d4abc757SPeter Tyser if (!env) 393*d4abc757SPeter Tyser /* no more env. variables to enumerate */ 394*d4abc757SPeter Tyser return NULL; 395*d4abc757SPeter Tyser 396*d4abc757SPeter Tyser /* next enumerated env var */ 397*d4abc757SPeter Tyser memset(env_name, 0, 256); 398*d4abc757SPeter Tyser for (i = 0, str = env; *str != '=' && *str != '\0';) 399*d4abc757SPeter Tyser env_name[i++] = *str++; 400*d4abc757SPeter Tyser 401*d4abc757SPeter Tyser env_name[i] = '\0'; 402*d4abc757SPeter Tyser 403*d4abc757SPeter Tyser return env_name; 404*d4abc757SPeter Tyser } 405