1/* 2 * stdlib support routines for self-contained images. 3 * Copyright 2007, Broadcom Corporation 4 * All Rights Reserved. 5 * 6 * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY 7 * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM 8 * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS 9 * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. 10 * $Id: bcmstdlib.c,v 1.1.1.1 2008/10/15 03:31:34 james26_jang Exp $ 11 */ 12 13/* 14 * bcmstdlib.c file should be used only to construct an OSL or alone without any OSL 15 * It should not be used with any orbitarary OSL's as there could be a conflict 16 * with some of the routines defined here. 17*/ 18 19#include <typedefs.h> 20#if defined(NDIS) || defined(_MINOSL_) || defined(__vxworks) || \ 21 defined(PCBIOS) || defined(LINUXSIM) || defined(EFI) 22/* debatable */ 23#include <osl.h> 24#elif 1 25#include <stdio.h> 26#endif 27 28/* 29 * Define BCMSTDLIB_WIN32_APP if this is a Win32 Application compile 30 */ 31#if defined(_WIN32) && !defined(NDIS) && !defined(EFI) 32#define BCMSTDLIB_WIN32_APP 1 33#endif /* _WIN32 && !NDIS */ 34 35/* 36 * Define BCMSTDLIB_SNPRINTF_ONLY if we only want snprintf & vsnprintf implementations 37 */ 38#if (defined(_WIN32) && !defined(EFI)) || defined(__vxworks) || defined(_CFE_) 39#define BCMSTDLIB_SNPRINTF_ONLY 1 40#endif 41 42#include <stdarg.h> 43#include <bcmstdlib.h> 44#ifndef BCMSTDLIB_WIN32_APP 45#include <bcmutils.h> 46#endif 47 48#ifdef BCMSTDLIB_WIN32_APP 49 50/* for a WIN32 application, use _vsnprintf as basis of vsnprintf/snprintf to 51 * support full set of format specifications. 52 */ 53 54int 55vsnprintf(char *buf, size_t bufsize, const char *fmt, va_list ap) 56{ 57 int r; 58 59 r = _vsnprintf(buf, bufsize, fmt, ap); 60 61 /* Microsoft _vsnprintf() will not null terminate on overflow, 62 * so null terminate at buffer end on error 63 */ 64 if (r < 0 && bufsize > 0) 65 buf[bufsize - 1] = '\0'; 66 67 return r; 68} 69 70int 71snprintf(char *buf, size_t bufsize, const char *fmt, ...) 72{ 73 va_list ap; 74 int r; 75 76 va_start(ap, fmt); 77 r = vsnprintf(buf, bufsize, fmt, ap); 78 va_end(ap); 79 80 return r; 81} 82 83#else /* BCMSTDLIB_WIN32_APP */ 84 85 86static const char digits[17] = "0123456789ABCDEF"; 87static const char ldigits[17] = "0123456789abcdef"; 88 89static int 90__atox(char *buf, char * end, unsigned int num, unsigned int radix, int width, 91 const char *digits) 92{ 93 char buffer[16]; 94 char *op; 95 int retval; 96 97 op = &buffer[0]; 98 retval = 0; 99 100 do { 101 *op++ = digits[num % radix]; 102 retval++; 103 num /= radix; 104 } while (num != 0); 105 106 if (width && (width > retval)) { 107 width = width - retval; 108 while (width) { 109 *op++ = '0'; 110 retval++; 111 width--; 112 } 113 } 114 115 while (op != buffer) { 116 op--; 117 if (buf <= end) 118 *buf = *op; 119 buf++; 120 } 121 122 return retval; 123} 124 125int 126BCMROMFN(vsnprintf)(char *buf, size_t size, const char *fmt, va_list ap) 127{ 128 char *optr; 129 char *end; 130 const char *iptr; 131 unsigned char *tmpptr; 132 unsigned int x; 133 int i; 134 int leadingzero; 135 int leadingnegsign; 136 int islong; 137 int width; 138 int width2 = 0; 139 int hashash = 0; 140 141 optr = buf; 142 end = buf + size - 1; 143 iptr = fmt; 144 145 if (end < buf - 1) { 146 end = ((void *) -1); 147 size = end - buf + 1; 148 } 149 150 while (*iptr) { 151 if (*iptr != '%') { 152 if (optr <= end) 153 *optr = *iptr; 154 ++optr; 155 ++iptr; 156 continue; 157 } 158 159 iptr++; 160 161 if (*iptr == '#') { 162 hashash = 1; 163 iptr++; 164 } 165 if (*iptr == '-') { 166 leadingnegsign = 1; 167 iptr++; 168 } else 169 leadingnegsign = 0; 170 171 if (*iptr == '0') 172 leadingzero = 1; 173 else 174 leadingzero = 0; 175 176 width = 0; 177 while (*iptr && bcm_isdigit(*iptr)) { 178 width += (*iptr - '0'); 179 iptr++; 180 if (bcm_isdigit(*iptr)) 181 width *= 10; 182 } 183 if (*iptr == '.') { 184 iptr++; 185 width2 = 0; 186 while (*iptr && bcm_isdigit(*iptr)) { 187 width2 += (*iptr - '0'); 188 iptr++; 189 if (bcm_isdigit(*iptr)) width2 *= 10; 190 } 191 } 192 193 islong = 0; 194 if (*iptr == 'l') { 195 islong++; 196 iptr++; 197 } 198 199 switch (*iptr) { 200 case 's': 201 tmpptr = (unsigned char *) va_arg(ap, unsigned char *); 202 if (!tmpptr) tmpptr = (unsigned char *) "(null)"; 203 if ((width == 0) & (width2 == 0)) { 204 while (*tmpptr) { 205 if (optr <= end) 206 *optr = *tmpptr; 207 ++optr; 208 ++tmpptr; 209 } 210 break; 211 } 212 while (width && *tmpptr) { 213 if (optr <= end) 214 *optr = *tmpptr; 215 ++optr; 216 ++tmpptr; 217 width--; 218 } 219 while (width) { 220 if (optr <= end) 221 *optr = ' '; 222 ++optr; 223 width--; 224 } 225 break; 226 case 'd': 227 case 'i': 228 i = va_arg(ap, int); 229 if (i < 0) { 230 if (optr <= end) 231 *optr = '-'; 232 ++optr; 233 i = -i; 234 } 235 optr += __atox(optr, end, i, 10, width, digits); 236 break; 237 case 'u': 238 x = va_arg(ap, unsigned int); 239 optr += __atox(optr, end, x, 10, width, digits); 240 break; 241 case 'X': 242 case 'x': 243 x = va_arg(ap, unsigned int); 244 optr += __atox(optr, end, x, 16, width, 245 (*iptr == 'X') ? digits : ldigits); 246 break; 247 case 'p': 248 case 'P': 249 x = va_arg(ap, unsigned int); 250 optr += __atox(optr, end, x, 16, 8, 251 (*iptr == 'P') ? digits : ldigits); 252 break; 253 case 'c': 254 x = va_arg(ap, int); 255 if (optr <= end) 256 *optr = x & 0xff; 257 optr++; 258 break; 259 260 default: 261 if (optr <= end) 262 *optr = *iptr; 263 optr++; 264 break; 265 } 266 iptr++; 267 } 268 269 if (optr <= end) { 270 *optr = '\0'; 271 return (int)(optr - buf); 272 } else { 273 *end = '\0'; 274 return (int)(end - buf); 275 } 276} 277 278 279int 280BCMROMFN(snprintf)(char *buf, size_t bufsize, const char *fmt, ...) 281{ 282 va_list ap; 283 int r; 284 285 va_start(ap, fmt); 286 r = vsnprintf(buf, bufsize, fmt, ap); 287 va_end(ap); 288 289 return r; 290} 291 292#endif /* BCMSTDLIB_WIN32_APP */ 293 294#ifndef BCMSTDLIB_SNPRINTF_ONLY 295 296 297int 298BCMROMFN(vsprintf)(char *buf, const char *fmt, va_list ap) 299{ 300 return (vsnprintf(buf, INT_MAX, fmt, ap)); 301} 302 303 304int 305BCMROMFN(sprintf)(char *buf, const char *fmt, ...) 306{ 307 va_list ap; 308 int count; 309 310 va_start(ap, fmt); 311 count = vsprintf(buf, fmt, ap); 312 va_end(ap); 313 314 return count; 315} 316 317 318void * 319BCMROMFN(memmove)(void *dest, const void *src, size_t n) 320{ 321 unsigned char *d; 322 const unsigned char *s; 323 324 /* only use memmove if dest is after source, otherwise use memcopy */ 325 if (src < dest) 326 return memcpy(dest, src, n); 327 328 /* do what memcpy does, but starting at the end and work backwords */ 329 d = (unsigned char *)dest + (n-1); 330 s = (const unsigned char *)src + (n-1); 331 332 while (n) { 333 *d-- = *s--; 334 n--; 335 } 336 337 return dest; 338} 339 340#ifndef EFI 341int 342BCMROMFN(memcmp)(const void *s1, const void *s2, size_t n) 343{ 344 const unsigned char *ss1; 345 const unsigned char *ss2; 346 347 ss1 = (const unsigned char *)s1; 348 ss2 = (const unsigned char *)s2; 349 350 while (n) { 351 if (*ss1 < *ss2) 352 return -1; 353 if (*ss1 > *ss2) 354 return 1; 355 ss1++; 356 ss2++; 357 n--; 358 } 359 360 return 0; 361} 362 363/* Skip over functions that are being used from DriverLibrary to save space */ 364char * 365BCMROMFN(strcpy)(char *dest, const char *src) 366{ 367 char *ptr = dest; 368 369 while ((*ptr++ = *src++) != '\0') 370 ; 371 372 return dest; 373} 374 375char * 376BCMROMFN(strncpy)(char *dest, const char *src, size_t n) 377{ 378 char *endp; 379 char *p; 380 381 p = dest; 382 endp = p + n; 383 384 while (p != endp && (*p++ = *src++) != '\0') 385 ; 386 387 /* zero fill remainder */ 388 while (p != endp) 389 *p++ = '\0'; 390 391 return dest; 392} 393 394size_t 395BCMROMFN(strlen)(const char *s) 396{ 397 size_t n = 0; 398 399 while (*s) { 400 s++; 401 n++; 402 } 403 404 return n; 405} 406 407int 408BCMROMFN(strcmp)(const char *s1, const char *s2) 409{ 410 while (*s2 && *s1) { 411 if (*s1 < *s2) 412 return -1; 413 if (*s1 > *s2) 414 return 1; 415 s1++; 416 s2++; 417 } 418 419 if (*s1 && !*s2) 420 return 1; 421 if (!*s1 && *s2) 422 return -1; 423 return 0; 424} 425#endif /* EFI */ 426 427int 428BCMROMFN(strncmp)(const char *s1, const char *s2, size_t n) 429{ 430 while (*s2 && *s1 && n) { 431 if (*s1 < *s2) 432 return -1; 433 if (*s1 > *s2) 434 return 1; 435 s1++; 436 s2++; 437 n--; 438 } 439 440 if (!n) 441 return 0; 442 if (*s1 && !*s2) 443 return 1; 444 if (!*s1 && *s2) 445 return -1; 446 return 0; 447} 448 449char * 450BCMROMFN(strchr)(const char *str, int c) 451{ 452 char *x = (char *)str; 453 454 while (*x != (char)c) { 455 if (*x++ == '\0') 456 return (NULL); 457 } 458 return (x); 459} 460 461char * 462BCMROMFN(strrchr)(const char *str, int c) 463{ 464 char *save = NULL; 465 466 do { 467 if (*str == (char) c) 468 save = (char*)(str); 469 } while (*str++ != '\0'); 470 471 return (save); 472} 473 474/* Skip over functions that are being used from DriverLibrary to save space */ 475#ifndef EFI 476char * 477BCMROMFN(strcat)(char *d, const char *s) 478{ 479 strcpy(&d[strlen(d)], s); 480 return (d); 481} 482#endif /* EFI */ 483 484char * 485BCMROMFN(index)(const char *s, int c) 486{ 487 /* Terminating NUL is considered part of string */ 488 489 for (; *s != c; s++) 490 if (!*s) 491 return NULL; 492 493 return (char *)s; 494} 495 496/* Skip over functions that are being used from DriverLibrary to save space */ 497#ifndef EFI 498char * 499BCMROMFN(strstr)(const char *s, const char *substr) 500{ 501 int substr_len = strlen(substr); 502 503 for (; *s; s++) 504 if (strncmp(s, substr, substr_len) == 0) 505 return (char *)s; 506 507 return NULL; 508} 509#endif /* EFI */ 510 511size_t 512BCMROMFN(strspn)(const char *s, const char *accept) 513{ 514 uint count = 0; 515 516 while (s[count] && index(accept, s[count])) 517 count++; 518 519 return count; 520} 521 522size_t 523BCMROMFN(strcspn)(const char *s, const char *reject) 524{ 525 uint count = 0; 526 527 while (s[count] && !index(reject, s[count])) 528 count++; 529 530 return count; 531} 532 533void * 534BCMROMFN(memchr)(const void *s, int c, size_t n) 535{ 536 if (n != 0) { 537 const unsigned char *ptr = s; 538 539 do { 540 if (*ptr == (unsigned char)c) 541 return (void *)ptr; 542 ptr++; 543 n--; 544 } while (n != 0); 545 } 546 return NULL; 547} 548 549unsigned long 550BCMROMFN(strtoul)(const char *cp, char **endp, int base) 551{ 552 ulong result, value; 553 bool minus; 554 555 minus = FALSE; 556 557 while (bcm_isspace(*cp)) 558 cp++; 559 560 if (cp[0] == '+') 561 cp++; 562 else if (cp[0] == '-') { 563 minus = TRUE; 564 cp++; 565 } 566 567 if (base == 0) { 568 if (cp[0] == '0') { 569 if ((cp[1] == 'x') || (cp[1] == 'X')) { 570 base = 16; 571 cp = &cp[2]; 572 } else { 573 base = 8; 574 cp = &cp[1]; 575 } 576 } else 577 base = 10; 578 } else if (base == 16 && (cp[0] == '0') && ((cp[1] == 'x') || (cp[1] == 'X'))) { 579 cp = &cp[2]; 580 } 581 582 result = 0; 583 584 while (bcm_isxdigit(*cp) && 585 (value = bcm_isdigit(*cp) ? *cp - '0' : bcm_toupper(*cp) - 'A' + 10) < 586 (ulong) base) { 587 result = result * base + value; 588 cp++; 589 } 590 591 if (minus) 592 result = (ulong)(result * -1); 593 594 if (endp) 595 *endp = (char *)cp; 596 597 return (result); 598} 599 600#ifndef EFI 601/* memset is not in ROM offload because it is used directly by the compiler in 602 * structure assignments/character array initialization with "". 603 */ 604void * 605memset(void *dest, int c, size_t n) 606{ 607 uint32 w, *dw; 608 unsigned char *d; 609 610 611 dw = (uint32 *)dest; 612 613 /* 8 min because we have to create w */ 614 if ((n >= 8) && (((uint)dest & 3) == 0)) { 615 if (c == 0) 616 w = 0; 617 else { 618 unsigned char ch; 619 620 ch = (unsigned char)(c & 0xff); 621 w = (ch << 8) | ch; 622 w |= w << 16; 623 } 624 while (n >= 4) { 625 *dw++ = w; 626 n -= 4; 627 } 628 } 629 d = (unsigned char *)dw; 630 631 while (n) { 632 *d++ = (unsigned char)c; 633 n--; 634 } 635 636 return d; 637} 638 639/* memcpy is not in ROM offload because it is used directly by the compiler in 640 * structure assignments. 641 */ 642void * 643memcpy(void *dest, const void *src, size_t n) 644{ 645 uint32 *dw; 646 const uint32 *sw; 647 unsigned char *d; 648 const unsigned char *s; 649 650 sw = (const uint32 *)src; 651 dw = (uint32 *)dest; 652 if ((n >= 4) && (((uint)src & 3) == 0) && (((uint)dest & 3) == 0)) { 653 while (n >= 4) { 654 *dw++ = *sw++; 655 n -= 4; 656 } 657 } 658 d = (unsigned char *)dw; 659 s = (const unsigned char *)sw; 660 while (n) { 661 *d++ = *s++; 662 n--; 663 } 664 665 return dest; 666} 667#endif /* EFI */ 668 669/* Include printf if it has already not been defined as NULL */ 670#ifndef printf 671int 672printf(const char *fmt, ...) 673{ 674 va_list ap; 675 int count, i; 676 char buffer[PRINTF_BUFLEN + 1]; 677 678 va_start(ap, fmt); 679 count = vsnprintf(buffer, sizeof(buffer), fmt, ap); 680 va_end(ap); 681 682 for (i = 0; i < count; i++) { 683 putc(buffer[i]); 684 685#ifdef EFI 686 if (buffer[i] == '\n') 687 putc('\r'); 688#endif 689 } 690 691 return count; 692} 693#endif /* printf */ 694 695int 696fputs(const char *s, FILE *stream /* UNUSED */) 697{ 698 char c; 699 while ((c = *s++)) 700 putchar(c); 701 return 0; 702} 703 704int 705puts(const char *s) 706{ 707 fputs(s, stdout); 708 putchar('\n'); 709 return 0; 710} 711 712int 713fputc(int c, FILE *stream /* UNUSED */) 714{ 715 putc(c); 716 return (int)(unsigned char)c; 717} 718 719 720unsigned long 721rand(void) 722{ 723 static unsigned long seed = 1; 724 long x, hi, lo, t; 725 726 x = seed; 727 hi = x / 127773; 728 lo = x % 127773; 729 t = 16807 * lo - 2836 * hi; 730 if (t <= 0) t += 0x7fffffff; 731 seed = t; 732 return t; 733} 734#endif /* BCMSTDLIB_SNPRINTF_ONLY */ 735