glue.c revision 177108
119304Speter/*- 219304Speter * Copyright (c) 2007 Semihalf, Rafal Jaworowski <raj@semihalf.com> 319304Speter * All rights reserved. 419304Speter * 519304Speter * Redistribution and use in source and binary forms, with or without 619304Speter * modification, are permitted provided that the following conditions 719304Speter * are met: 819304Speter * 1. Redistributions of source code must retain the above copyright 919304Speter * notice, this list of conditions and the following disclaimer. 1019304Speter * 2. Redistributions in binary form must reproduce the above copyright 1119304Speter * notice, this list of conditions and the following disclaimer in the 1219304Speter * documentation and/or other materials provided with the distribution. 13254225Speter * 1419304Speter * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1519304Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1619304Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1719304Speter * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1819304Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1919304Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2019304Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2119304Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2219304Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2319304Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2419304Speter * SUCH DAMAGE. 2519304Speter */ 2619304Speter 2719304Speter#include <sys/cdefs.h> 2819304Speter__FBSDID("$FreeBSD: head/sys/boot/uboot/lib/glue.c 177108 2008-03-12 16:01:34Z raj $"); 2919304Speter 3019304Speter#include <stand.h> 3119304Speter#include "api_public.h" 3219304Speter#include "glue.h" 3319304Speter 3419304Speter#define DEBUG 3519304Speter#undef DEBUG 3619304Speter 37254225Speter#ifdef DEBUG 3819304Speter#define debugf(fmt, args...) do { printf("%s(): ", __func__); printf(fmt,##args); } while (0) 3919304Speter#else 4019304Speter#define debugf(fmt, args...) 4119304Speter#endif 4219304Speter 4319304Speter/* Some random address used by U-Boot. */ 4419304Speterextern long uboot_address; 4519304Speter 4619304Speter/* crc32 stuff stolen from lib/libdisk/write_ia64_disk.c */ 4719304Speterstatic uint32_t crc32_tab[] = { 4819304Speter 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 4919304Speter 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 5019304Speter 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 5119304Speter 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 5219304Speter 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 5319304Speter 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 5419304Speter 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 5519304Speter 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 5619304Speter 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 5719304Speter 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 5819304Speter 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 5919304Speter 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 60254225Speter 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 61254225Speter 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 62254225Speter 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 63254225Speter 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 64254225Speter 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 6519304Speter 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 6619304Speter 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 6719304Speter 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 6819304Speter 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 6919304Speter 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 7019304Speter 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 7119304Speter 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 7219304Speter 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 7319304Speter 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 7419304Speter 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 7519304Speter 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 7619304Speter 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 7719304Speter 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 7819304Speter 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 7919304Speter 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 8019304Speter 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 8119304Speter 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 8219304Speter 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 8319304Speter 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 8419304Speter 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 85254225Speter 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 8619304Speter 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 8719304Speter 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 8819304Speter 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 8919304Speter 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 9019304Speter 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d 9119304Speter}; 9219304Speter 9319304Speterstatic uint32_t 9419304Spetercrc32(const void *buf, size_t size) 95254225Speter{ 96254225Speter const uint8_t *p; 9719304Speter uint32_t crc; 9819304Speter 9919304Speter p = buf; 10019304Speter crc = ~0U; 10119304Speter 10219304Speter while (size--) 10319304Speter crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8); 10419304Speter 10519304Speter return (crc ^ ~0U); 10619304Speter} 10719304Speter 10819304Speter 10919304Speterstatic int valid_sig(struct api_signature *sig) 11019304Speter{ 11119304Speter uint32_t checksum; 11219304Speter struct api_signature s; 11319304Speter 11419304Speter if (sig == NULL) 11519304Speter return (0); 116254225Speter /* 11719304Speter * Clear the checksum field (in the local copy) so as to calculate the 11819304Speter * CRC with the same initial contents as at the time when the sig was 119254225Speter * produced 120254225Speter */ 12119304Speter s = *sig; 12219304Speter s.checksum = 0; 12319304Speter 12419304Speter checksum = crc32((void *)&s, sizeof(struct api_signature)); 12519304Speter 12619304Speter if (checksum != sig->checksum) 12719304Speter return (0); 12819304Speter 12919304Speter return (1); 130} 131 132/* 133 * Searches for the U-Boot API signature 134 * 135 * returns 1/0 depending on found/not found result 136 */ 137int api_search_sig(struct api_signature **sig) { 138 139 unsigned char *sp, *spend; 140 141 if (sig == NULL) 142 return (0); 143 144 if (uboot_address == 0) 145 uboot_address = 255 * 1024 * 1024; 146 147 sp = (void *)(uboot_address & ~0x000fffff); 148 spend = sp + 0x00100000 - API_SIG_MAGLEN; 149 while (sp < spend) { 150 if (!bcmp(sp, API_SIG_MAGIC, API_SIG_MAGLEN)) { 151 *sig = (struct api_signature *)sp; 152 if (valid_sig(*sig)) 153 return (1); 154 } 155 sp += API_SIG_MAGLEN; 156 } 157 158 *sig = NULL; 159 return (0); 160} 161 162/**************************************** 163 * 164 * console 165 * 166 ****************************************/ 167 168int ub_getc(void) 169{ 170 int c; 171 172 if (!syscall(API_GETC, NULL, (uint32_t)&c)) 173 return (-1); 174 175 return c; 176} 177 178int ub_tstc(void) 179{ 180 int t; 181 182 if (!syscall(API_TSTC, NULL, (uint32_t)&t)) 183 return (-1); 184 185 return t; 186} 187 188void ub_putc(char c) 189{ 190 syscall(API_PUTC, NULL, (uint32_t)&c); 191} 192 193void ub_puts(const char *s) 194{ 195 syscall(API_PUTS, NULL, (uint32_t)s); 196} 197 198/**************************************** 199 * 200 * system 201 * 202 ****************************************/ 203 204void ub_reset(void) 205{ 206 syscall(API_RESET, NULL); 207} 208 209 210#define MR_MAX 5 211static struct mem_region mr[MR_MAX]; 212static struct sys_info si; 213 214struct sys_info * ub_get_sys_info(void) 215{ 216 int err = 0; 217 218 memset(&si, 0, sizeof(struct sys_info)); 219 si.mr = mr; 220 si.mr_no = MR_MAX; 221 memset(&mr, 0, sizeof(mr)); 222 223 if (!syscall(API_GET_SYS_INFO, &err, (u_int32_t)&si)) 224 return (NULL); 225 226 return ((err) ? NULL : &si); 227} 228 229 230/**************************************** 231 * 232 * timing 233 * 234 ****************************************/ 235 236void ub_udelay(unsigned long usec) 237{ 238 239 syscall(API_UDELAY, NULL, &usec); 240} 241 242unsigned long ub_get_timer(unsigned long base) 243{ 244 unsigned long cur; 245 246 if (!syscall(API_GET_TIMER, NULL, &cur, &base)) 247 return (0); 248 249 return (cur); 250} 251 252 253/**************************************************************************** 254 * 255 * devices 256 * 257 * Devices are identified by handles: numbers 0, 1, 2, ..., MAX_DEVS-1 258 * 259 ***************************************************************************/ 260 261#define MAX_DEVS 6 262 263static struct device_info devices[MAX_DEVS]; 264 265struct device_info * ub_dev_get(int i) 266{ 267 return ((i < 0 || i >= MAX_DEVS) ? NULL : &devices[i]); 268} 269 270/* 271 * Enumerates the devices: fills out device_info elements in the devices[] 272 * array. 273 * 274 * returns: number of devices found 275 */ 276int ub_dev_enum(void) 277{ 278 struct device_info *di; 279 int n = 0; 280 281 memset(&devices, 0, sizeof(struct device_info) * MAX_DEVS); 282 di = &devices[0]; 283 284 if (!syscall(API_DEV_ENUM, NULL, di)) 285 return (0); 286 287 while (di->cookie != NULL) { 288 289 if (++n >= MAX_DEVS) 290 break; 291 292 /* take another device_info */ 293 di++; 294 295 /* pass on the previous cookie */ 296 di->cookie = devices[n - 1].cookie; 297 298 if (!syscall(API_DEV_ENUM, NULL, di)) 299 return 0; 300 } 301 302 return (n); 303} 304 305 306/* 307 * handle: 0-based id of the device 308 * 309 * returns: 0 when OK, err otherwise 310 */ 311int ub_dev_open(int handle) 312{ 313 struct device_info *di; 314 int err = 0; 315 316 if (handle < 0 || handle >= MAX_DEVS) 317 return (API_EINVAL); 318 319 di = &devices[handle]; 320 if (!syscall(API_DEV_OPEN, &err, di)) 321 return (-1); 322 323 return (err); 324} 325 326int ub_dev_close(int handle) 327{ 328 struct device_info *di; 329 330 if (handle < 0 || handle >= MAX_DEVS) 331 return (API_EINVAL); 332 333 di = &devices[handle]; 334 if (!syscall(API_DEV_CLOSE, NULL, di)) 335 return (-1); 336 337 return (0); 338} 339 340/* 341 * Validates device for read/write, it has to: 342 * 343 * - have sane handle 344 * - be opened 345 * 346 * returns: 0/1 accordingly 347 */ 348static int dev_valid(int handle) 349{ 350 351 if (handle < 0 || handle >= MAX_DEVS) 352 return (0); 353 354 if (devices[handle].state != DEV_STA_OPEN) 355 return (0); 356 357 return (1); 358} 359 360static int dev_stor_valid(int handle) 361{ 362 363 if (!dev_valid(handle)) 364 return (0); 365 366 if (!(devices[handle].type & DEV_TYP_STOR)) 367 return (0); 368 369 return (1); 370} 371 372int ub_dev_read(int handle, void *buf, lbasize_t len, lbastart_t start) 373{ 374 struct device_info *di; 375 lbasize_t act_len; 376 int err = 0; 377 378 if (!dev_stor_valid(handle)) 379 return (API_ENODEV); 380 381 di = &devices[handle]; 382 if (!syscall(API_DEV_READ, &err, di, buf, &len, &start, &act_len)) 383 return (-1); 384 385 if (err) 386 return (err); 387 388 if (act_len != len) 389 return (API_EIO); 390 391 return (0); 392} 393 394static int dev_net_valid(int handle) 395{ 396 397 if (!dev_valid(handle)) 398 return (0); 399 400 if (devices[handle].type != DEV_TYP_NET) 401 return (0); 402 403 return (1); 404} 405 406int ub_dev_recv(int handle, void *buf, int len) 407{ 408 struct device_info *di; 409 int err = 0, act_len; 410 411 if (!dev_net_valid(handle)) 412 return (API_ENODEV); 413 414 di = &devices[handle]; 415 if (!syscall(API_DEV_READ, &err, di, buf, &len, &act_len)) 416 return (-1); 417 418 if (err) 419 return (-1); 420 421 return (act_len); 422} 423 424int ub_dev_send(int handle, void *buf, int len) 425{ 426 struct device_info *di; 427 int err = 0; 428 429 if (!dev_net_valid(handle)) 430 return (API_ENODEV); 431 432 di = &devices[handle]; 433 if (!syscall(API_DEV_WRITE, &err, di, buf, &len)) 434 return (-1); 435 436 return (err); 437} 438 439/**************************************** 440 * 441 * env vars 442 * 443 ****************************************/ 444 445char * ub_env_get(const char *name) 446{ 447 char *value; 448 449 if (!syscall(API_ENV_GET, NULL, (uint32_t)name, (uint32_t)&value)) 450 return (NULL); 451 452 return (value); 453} 454 455void ub_env_set(const char *name, char *value) 456{ 457 458 syscall(API_ENV_SET, NULL, (uint32_t)name, (uint32_t)value); 459} 460 461 462static char env_name[256]; 463 464const char * ub_env_enum(const char *last) 465{ 466 const char *env, *str; 467 int i; 468 469 env = NULL; 470 471 /* 472 * It's OK to pass only the name piece as last (and not the whole 473 * 'name=val' string), since the API_ENUM_ENV call uses envmatch() 474 * internally, which handles such case 475 */ 476 if (!syscall(API_ENV_ENUM, NULL, (uint32_t)last, (uint32_t)&env)) 477 return (NULL); 478 479 if (!env) 480 /* no more env. variables to enumerate */ 481 return (NULL); 482#if 0 483 if (last && strncmp(env, last, strlen(last)) == 0); 484 /* error, trying to enumerate non existing env. variable */ 485 return NULL; 486#endif 487 488 /* next enumerated env var */ 489 memset(env_name, 0, 256); 490 for (i = 0, str = env; *str != '=' && *str != '\0';) 491 env_name[i++] = *str++; 492 493 env_name[i] = '\0'; 494 495 return (env_name); 496} 497