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