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