/* * stdlib support routines for self-contained images. * Copyright 2007, Broadcom Corporation * All Rights Reserved. * * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. * $Id: bcmstdlib.c,v 1.1.1.1 2008/07/21 09:20:53 james26_jang Exp $ */ /* * bcmstdlib.c file should be used only to construct an OSL or alone without any OSL * It should not be used with any orbitarary OSL's as there could be a conflict * with some of the routines defined here. */ #include #if defined(NDIS) || defined(_MINOSL_) || defined(__vxworks) || \ defined(PCBIOS) || defined(LINUXSIM) || defined(EFI) /* debatable */ #include #elif 1 #include #endif /* * Define BCMSTDLIB_WIN32_APP if this is a Win32 Application compile */ #if defined(_WIN32) && !defined(NDIS) && !defined(EFI) #define BCMSTDLIB_WIN32_APP 1 #endif /* _WIN32 && !NDIS */ /* * Define BCMSTDLIB_SNPRINTF_ONLY if we only want snprintf & vsnprintf implementations */ #if (defined(_WIN32) && !defined(EFI)) || defined(__vxworks) || defined(_CFE_) #define BCMSTDLIB_SNPRINTF_ONLY 1 #endif #include #include #ifndef BCMSTDLIB_WIN32_APP #include #endif #ifdef BCMSTDLIB_WIN32_APP /* for a WIN32 application, use _vsnprintf as basis of vsnprintf/snprintf to * support full set of format specifications. */ int vsnprintf(char *buf, size_t bufsize, const char *fmt, va_list ap) { int r; r = _vsnprintf(buf, bufsize, fmt, ap); /* Microsoft _vsnprintf() will not null terminate on overflow, * so null terminate at buffer end on error */ if (r < 0 && bufsize > 0) buf[bufsize - 1] = '\0'; return r; } int snprintf(char *buf, size_t bufsize, const char *fmt, ...) { va_list ap; int r; va_start(ap, fmt); r = vsnprintf(buf, bufsize, fmt, ap); va_end(ap); return r; } #else /* BCMSTDLIB_WIN32_APP */ static const char digits[17] = "0123456789ABCDEF"; static const char ldigits[17] = "0123456789abcdef"; static int __atox(char *buf, char * end, unsigned int num, unsigned int radix, int width, const char *digits) { char buffer[16]; char *op; int retval; op = &buffer[0]; retval = 0; do { *op++ = digits[num % radix]; retval++; num /= radix; } while (num != 0); if (width && (width > retval)) { width = width - retval; while (width) { *op++ = '0'; retval++; width--; } } while (op != buffer) { op--; if (buf <= end) *buf = *op; buf++; } return retval; } int BCMROMFN(vsnprintf)(char *buf, size_t size, const char *fmt, va_list ap) { char *optr; char *end; const char *iptr; unsigned char *tmpptr; unsigned int x; int i; int leadingzero; int leadingnegsign; int islong; int width; int width2 = 0; int hashash = 0; optr = buf; end = buf + size - 1; iptr = fmt; if (end < buf - 1) { end = ((void *) -1); size = end - buf + 1; } while (*iptr) { if (*iptr != '%') { if (optr <= end) *optr = *iptr; ++optr; ++iptr; continue; } iptr++; if (*iptr == '#') { hashash = 1; iptr++; } if (*iptr == '-') { leadingnegsign = 1; iptr++; } else leadingnegsign = 0; if (*iptr == '0') leadingzero = 1; else leadingzero = 0; width = 0; while (*iptr && bcm_isdigit(*iptr)) { width += (*iptr - '0'); iptr++; if (bcm_isdigit(*iptr)) width *= 10; } if (*iptr == '.') { iptr++; width2 = 0; while (*iptr && bcm_isdigit(*iptr)) { width2 += (*iptr - '0'); iptr++; if (bcm_isdigit(*iptr)) width2 *= 10; } } islong = 0; if (*iptr == 'l') { islong++; iptr++; } switch (*iptr) { case 's': tmpptr = (unsigned char *) va_arg(ap, unsigned char *); if (!tmpptr) tmpptr = (unsigned char *) "(null)"; if ((width == 0) & (width2 == 0)) { while (*tmpptr) { if (optr <= end) *optr = *tmpptr; ++optr; ++tmpptr; } break; } while (width && *tmpptr) { if (optr <= end) *optr = *tmpptr; ++optr; ++tmpptr; width--; } while (width) { if (optr <= end) *optr = ' '; ++optr; width--; } break; case 'd': case 'i': i = va_arg(ap, int); if (i < 0) { if (optr <= end) *optr = '-'; ++optr; i = -i; } optr += __atox(optr, end, i, 10, width, digits); break; case 'u': x = va_arg(ap, unsigned int); optr += __atox(optr, end, x, 10, width, digits); break; case 'X': case 'x': x = va_arg(ap, unsigned int); optr += __atox(optr, end, x, 16, width, (*iptr == 'X') ? digits : ldigits); break; case 'p': case 'P': x = va_arg(ap, unsigned int); optr += __atox(optr, end, x, 16, 8, (*iptr == 'P') ? digits : ldigits); break; case 'c': x = va_arg(ap, int); if (optr <= end) *optr = x & 0xff; optr++; break; default: if (optr <= end) *optr = *iptr; optr++; break; } iptr++; } if (optr <= end) { *optr = '\0'; return (int)(optr - buf); } else { *end = '\0'; return (int)(end - buf); } } int BCMROMFN(snprintf)(char *buf, size_t bufsize, const char *fmt, ...) { va_list ap; int r; va_start(ap, fmt); r = vsnprintf(buf, bufsize, fmt, ap); va_end(ap); return r; } #endif /* BCMSTDLIB_WIN32_APP */ #ifndef BCMSTDLIB_SNPRINTF_ONLY int BCMROMFN(vsprintf)(char *buf, const char *fmt, va_list ap) { return (vsnprintf(buf, INT_MAX, fmt, ap)); } int BCMROMFN(sprintf)(char *buf, const char *fmt, ...) { va_list ap; int count; va_start(ap, fmt); count = vsprintf(buf, fmt, ap); va_end(ap); return count; } void * BCMROMFN(memmove)(void *dest, const void *src, size_t n) { unsigned char *d; const unsigned char *s; /* only use memmove if dest is after source, otherwise use memcopy */ if (src < dest) return memcpy(dest, src, n); /* do what memcpy does, but starting at the end and work backwords */ d = (unsigned char *)dest + (n-1); s = (const unsigned char *)src + (n-1); while (n) { *d-- = *s--; n--; } return dest; } #ifndef EFI int BCMROMFN(memcmp)(const void *s1, const void *s2, size_t n) { const unsigned char *ss1; const unsigned char *ss2; ss1 = (const unsigned char *)s1; ss2 = (const unsigned char *)s2; while (n) { if (*ss1 < *ss2) return -1; if (*ss1 > *ss2) return 1; ss1++; ss2++; n--; } return 0; } /* Skip over functions that are being used from DriverLibrary to save space */ char * BCMROMFN(strcpy)(char *dest, const char *src) { char *ptr = dest; while ((*ptr++ = *src++) != '\0') ; return dest; } char * BCMROMFN(strncpy)(char *dest, const char *src, size_t n) { char *endp; char *p; p = dest; endp = p + n; while (p != endp && (*p++ = *src++) != '\0') ; /* zero fill remainder */ while (p != endp) *p++ = '\0'; return dest; } size_t BCMROMFN(strlen)(const char *s) { size_t n = 0; while (*s) { s++; n++; } return n; } int BCMROMFN(strcmp)(const char *s1, const char *s2) { while (*s2 && *s1) { if (*s1 < *s2) return -1; if (*s1 > *s2) return 1; s1++; s2++; } if (*s1 && !*s2) return 1; if (!*s1 && *s2) return -1; return 0; } #endif /* EFI */ int BCMROMFN(strncmp)(const char *s1, const char *s2, size_t n) { while (*s2 && *s1 && n) { if (*s1 < *s2) return -1; if (*s1 > *s2) return 1; s1++; s2++; n--; } if (!n) return 0; if (*s1 && !*s2) return 1; if (!*s1 && *s2) return -1; return 0; } char * BCMROMFN(strchr)(const char *str, int c) { char *x = (char *)str; while (*x != (char)c) { if (*x++ == '\0') return (NULL); } return (x); } char * BCMROMFN(strrchr)(const char *str, int c) { char *save = NULL; do { if (*str == (char) c) save = (char*)(str); } while (*str++ != '\0'); return (save); } /* Skip over functions that are being used from DriverLibrary to save space */ #ifndef EFI char * BCMROMFN(strcat)(char *d, const char *s) { strcpy(&d[strlen(d)], s); return (d); } #endif /* EFI */ char * BCMROMFN(index)(const char *s, int c) { /* Terminating NUL is considered part of string */ for (; *s != c; s++) if (!*s) return NULL; return (char *)s; } /* Skip over functions that are being used from DriverLibrary to save space */ #ifndef EFI char * BCMROMFN(strstr)(const char *s, const char *substr) { int substr_len = strlen(substr); for (; *s; s++) if (strncmp(s, substr, substr_len) == 0) return (char *)s; return NULL; } #endif /* EFI */ size_t BCMROMFN(strspn)(const char *s, const char *accept) { uint count = 0; while (s[count] && index(accept, s[count])) count++; return count; } size_t BCMROMFN(strcspn)(const char *s, const char *reject) { uint count = 0; while (s[count] && !index(reject, s[count])) count++; return count; } void * BCMROMFN(memchr)(const void *s, int c, size_t n) { if (n != 0) { const unsigned char *ptr = s; do { if (*ptr == (unsigned char)c) return (void *)ptr; ptr++; n--; } while (n != 0); } return NULL; } unsigned long BCMROMFN(strtoul)(const char *cp, char **endp, int base) { ulong result, value; bool minus; minus = FALSE; while (bcm_isspace(*cp)) cp++; if (cp[0] == '+') cp++; else if (cp[0] == '-') { minus = TRUE; cp++; } if (base == 0) { if (cp[0] == '0') { if ((cp[1] == 'x') || (cp[1] == 'X')) { base = 16; cp = &cp[2]; } else { base = 8; cp = &cp[1]; } } else base = 10; } else if (base == 16 && (cp[0] == '0') && ((cp[1] == 'x') || (cp[1] == 'X'))) { cp = &cp[2]; } result = 0; while (bcm_isxdigit(*cp) && (value = bcm_isdigit(*cp) ? *cp - '0' : bcm_toupper(*cp) - 'A' + 10) < (ulong) base) { result = result * base + value; cp++; } if (minus) result = (ulong)(result * -1); if (endp) *endp = (char *)cp; return (result); } #ifndef EFI /* memset is not in ROM offload because it is used directly by the compiler in * structure assignments/character array initialization with "". */ void * memset(void *dest, int c, size_t n) { uint32 w, *dw; unsigned char *d; dw = (uint32 *)dest; /* 8 min because we have to create w */ if ((n >= 8) && (((uint)dest & 3) == 0)) { if (c == 0) w = 0; else { unsigned char ch; ch = (unsigned char)(c & 0xff); w = (ch << 8) | ch; w |= w << 16; } while (n >= 4) { *dw++ = w; n -= 4; } } d = (unsigned char *)dw; while (n) { *d++ = (unsigned char)c; n--; } return d; } /* memcpy is not in ROM offload because it is used directly by the compiler in * structure assignments. */ void * memcpy(void *dest, const void *src, size_t n) { uint32 *dw; const uint32 *sw; unsigned char *d; const unsigned char *s; sw = (const uint32 *)src; dw = (uint32 *)dest; if ((n >= 4) && (((uint)src & 3) == 0) && (((uint)dest & 3) == 0)) { while (n >= 4) { *dw++ = *sw++; n -= 4; } } d = (unsigned char *)dw; s = (const unsigned char *)sw; while (n) { *d++ = *s++; n--; } return dest; } #endif /* EFI */ /* Include printf if it has already not been defined as NULL */ #ifndef printf int printf(const char *fmt, ...) { va_list ap; int count, i; char buffer[PRINTF_BUFLEN + 1]; va_start(ap, fmt); count = vsnprintf(buffer, sizeof(buffer), fmt, ap); va_end(ap); for (i = 0; i < count; i++) { putc(buffer[i]); #ifdef EFI if (buffer[i] == '\n') putc('\r'); #endif } return count; } #endif /* printf */ int fputs(const char *s, FILE *stream /* UNUSED */) { char c; while ((c = *s++)) putchar(c); return 0; } int puts(const char *s) { fputs(s, stdout); putchar('\n'); return 0; } int fputc(int c, FILE *stream /* UNUSED */) { putc(c); return (int)(unsigned char)c; } unsigned long rand(void) { static unsigned long seed = 1; long x, hi, lo, t; x = seed; hi = x / 127773; lo = x % 127773; t = 16807 * lo - 2836 * hi; if (t <= 0) t += 0x7fffffff; seed = t; return t; } #endif /* BCMSTDLIB_SNPRINTF_ONLY */