xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/bcmstdlib.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * stdlib support routines for self-contained images.
3  *
4  * Copyright (C) 2020, Broadcom.
5  *
6  *      Unless you and Broadcom execute a separate written software license
7  * agreement governing use of this software, this software is licensed to you
8  * under the terms of the GNU General Public License version 2 (the "GPL"),
9  * available at http://www.broadcom.com/licenses/GPLv2.php, with the
10  * following added to such license:
11  *
12  *      As a special exception, the copyright holders of this software give you
13  * permission to link this software with independent modules, and to copy and
14  * distribute the resulting executable under terms of your choice, provided that
15  * you also meet, for each linked independent module, the terms and conditions of
16  * the license of that module.  An independent module is a module which is not
17  * derived from this software.  The special exception does not apply to any
18  * modifications of the software.
19  *
20  *
21  * <<Broadcom-WL-IPTag/Dual:>>
22  */
23 
24 /*
25  * bcmstdlib.c file should be used only to construct an OSL or alone without any OSL
26  * It should not be used with any orbitarary OSL's as there could be a conflict
27  * with some of the routines defined here.
28  */
29 
30 /*
31  * Define BCMSTDLIB_WIN32_APP if this is a Win32 Application compile
32  */
33 #if defined(_WIN32) && !defined(NDIS) && !defined(EFI)
34 #define BCMSTDLIB_WIN32_APP 1
35 #endif /* _WIN32 && !NDIS */
36 
37 /*
38  * Define BCMSTDLIB_SNPRINTF_ONLY if we only want snprintf & vsnprintf implementations
39  */
40 #if defined(_WIN32) && !defined(EFI)
41 #define BCMSTDLIB_SNPRINTF_ONLY 1
42 #endif /* _WIN32 || !EFI */
43 
44 #include <typedefs.h>
45 #ifdef BCMSTDLIB_WIN32_APP
46 /* for size_t definition */
47 #include <stddef.h>
48 #endif
49 #include <stdarg.h>
50 #ifndef BCMSTDLIB_WIN32_APP
51 #include <bcmutils.h>
52 #endif
53 #include <bcmstdlib.h>
54 
55 /* Don't use compiler builtins for stdlib APIs within the implementation of the stdlib itself. */
56 #if defined(BCM_FORTIFY_SOURCE) || defined(BCM_STDLIB_USE_BUILTINS)
57 #undef memcpy
58 #undef memmove
59 #undef memset
60 #undef strncpy
61 #undef snprintf
62 #undef vsnprintf
63 #endif	/* BCM_FORTIFY_SOURCE || BCM_STDLIB_USE_BUILTINS */
64 
65 #ifdef HND_PRINTF_THREAD_SAFE
66 #include <osl.h>
67 #include <osl_ext.h>
68 #include <bcmstdlib_ext.h>
69 
70 /* mutex macros for thread safe */
71 #define HND_PRINTF_MUTEX_DECL(mutex)		static OSL_EXT_MUTEX_DECL(mutex)
72 #define HND_PRINTF_MUTEX_CREATE(name, mutex)	osl_ext_mutex_create(name, mutex)
73 #define HND_PRINTF_MUTEX_DELETE(mutex)		osl_ext_mutex_delete(mutex)
74 #define HND_PRINTF_MUTEX_ACQUIRE(mutex, msec)	osl_ext_mutex_acquire(mutex, msec)
75 #define HND_PRINTF_MUTEX_RELEASE(mutex)	osl_ext_mutex_release(mutex)
76 
77 HND_PRINTF_MUTEX_DECL(printf_mutex);
78 int in_isr_handler = 0, in_trap_handler = 0, in_fiq_handler = 0;
79 
80 bool
printf_lock_init(void)81 printf_lock_init(void)
82 {
83 	/* create mutex for critical section locking */
84 	if (HND_PRINTF_MUTEX_CREATE("printf_mutex", &printf_mutex) != OSL_EXT_SUCCESS)
85 		return FALSE;
86 	return TRUE;
87 }
88 
89 bool
printf_lock_cleanup(void)90 printf_lock_cleanup(void)
91 {
92 	/* create mutex for critical section locking */
93 	if (HND_PRINTF_MUTEX_DELETE(&printf_mutex) != OSL_EXT_SUCCESS)
94 		return FALSE;
95 	return TRUE;
96 }
97 
98 /* returns TRUE if allowed to proceed, FALSE to discard.
99 * printf from isr hook or fiq hook is not allowed due to IRQ_MODE and FIQ_MODE stack size
100 * limitation.
101 */
102 static bool
printf_lock(void)103 printf_lock(void)
104 {
105 
106 	/* discard for irq or fiq context, we need to keep irq/fiq stack small. */
107 	if (in_isr_handler || in_fiq_handler)
108 		return FALSE;
109 
110 	/* allow printf in trap handler, proceed without mutex. */
111 	if (in_trap_handler)
112 		return TRUE;
113 
114 	/* if not in isr or trap, then go thread-protection with mutex. */
115 	if (HND_PRINTF_MUTEX_ACQUIRE(&printf_mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
116 		return FALSE;
117 	else
118 		return TRUE;
119 }
120 
121 static void
printf_unlock(void)122 printf_unlock(void)
123 {
124 	if (in_isr_handler || in_fiq_handler)
125 		return;
126 
127 	if (in_trap_handler)
128 		return;
129 
130 	if (HND_PRINTF_MUTEX_RELEASE(&printf_mutex) != OSL_EXT_SUCCESS)
131 		return;
132 }
133 
134 #else
135 #define printf_lock() (TRUE)
136 #define printf_unlock()
137 #endif	/* HND_PRINTF_THREAD_SAFE */
138 
139 #ifdef BCMSTDLIB_WIN32_APP
140 
141 /* for a WIN32 application, use _vsnprintf as basis of vsnprintf/snprintf to
142  * support full set of format specifications.
143  */
144 
145 int
BCMPOSTTRAPFN(vsnprintf)146 BCMPOSTTRAPFN(vsnprintf)(char *buf, size_t bufsize, const char *fmt, va_list ap)
147 {
148 	int r;
149 
150 	r = _vsnprintf(buf, bufsize, fmt, ap);
151 
152 	/* Microsoft _vsnprintf() will not null terminate on overflow,
153 	 * so null terminate at buffer end on error
154 	 */
155 	if (r < 0 && bufsize > 0)
156 		buf[bufsize - 1] = '\0';
157 
158 	return r;
159 }
160 
161 int
BCMPOSTTRAPFN(snprintf)162 BCMPOSTTRAPFN(snprintf)(char *buf, size_t bufsize, const char *fmt, ...)
163 {
164 	va_list	ap;
165 	int	r;
166 
167 	va_start(ap, fmt);
168 	r = vsnprintf(buf, bufsize, fmt, ap);
169 	va_end(ap);
170 
171 	return r;
172 }
173 
174 #else /* BCMSTDLIB_WIN32_APP */
175 
176 #if !defined(BCMROMOFFLOAD_EXCLUDE_STDLIB_FUNCS)
177 
178 static const char hex_upper[17] = "0123456789ABCDEF";
179 static const char hex_lower[17] = "0123456789abcdef";
180 
181 static int
BCMPOSTTRAPFN(__atolx)182 BCMPOSTTRAPFN(__atolx)(char *buf, char * end, unsigned long num, unsigned long radix, int width,
183        const char *digits, int zero_pad)
184 {
185 	char buffer[32];
186 	char *op;
187 	int retval;
188 
189 	op = &buffer[0];
190 	retval = 0;
191 
192 	do {
193 		*op++ = digits[num % radix];
194 		retval++;
195 		num /= radix;
196 	} while (num != 0);
197 
198 	if (width && (width > retval) && zero_pad) {
199 		width = width - retval;
200 		while (width) {
201 			*op++ = '0';
202 			retval++;
203 			width--;
204 		}
205 	}
206 
207 	while (op != buffer) {
208 		op--;
209 		if (buf <= end)
210 			*buf = *op;
211 		buf++;
212 	}
213 
214 	return retval;
215 }
216 
217 static int
BCMPOSTTRAPFN(__atox)218 BCMPOSTTRAPFN(__atox)(char *buf, char * end, unsigned int num, unsigned int radix, int width,
219        const char *digits, int zero_pad)
220 {
221 	char buffer[16];
222 	char *op;
223 	int retval;
224 
225 	op = &buffer[0];
226 	retval = 0;
227 
228 	do {
229 		*op++ = digits[num % radix];
230 		retval++;
231 		num /= radix;
232 	} while (num != 0);
233 
234 	if (width && (width > retval) && zero_pad) {
235 		width = width - retval;
236 		while (width) {
237 			*op++ = '0';
238 			retval++;
239 			width--;
240 		}
241 	}
242 
243 	while (op != buffer) {
244 		op--;
245 		if (buf <= end)
246 			*buf = *op;
247 		buf++;
248 	}
249 
250 	return retval;
251 }
252 
253 int
BCMPOSTTRAPFN(vsnprintf)254 BCMPOSTTRAPFN(vsnprintf)(char *buf, size_t size, const char *fmt, va_list ap)
255 {
256 	char *optr;
257 	char *end;
258 	const char *iptr, *tmpptr;
259 	unsigned int x;
260 	int i;
261 	int islong;
262 	int width;
263 	int width2 = 0;
264 	int hashash = 0;
265 	int zero_pad;
266 	unsigned long ul = 0;
267 	long int li = 0;
268 
269 	optr = buf;
270 	end = buf + size - 1;
271 	iptr = fmt;
272 
273 	if (FWSIGN_ENAB()) {
274 		return 0;
275 	}
276 
277 	if (end < buf - 1) {
278 		end = ((void *) -1);
279 		size = end - buf + 1;
280 	}
281 
282 	while (*iptr) {
283 		zero_pad = 0;
284 		if (*iptr != '%') {
285 			if (optr <= end)
286 				*optr = *iptr;
287 			++optr;
288 			++iptr;
289 			continue;
290 		}
291 
292 		iptr++;
293 
294 		if (*iptr == '#') {
295 			hashash = 1;
296 			iptr++;
297 		}
298 		if (*iptr == '-') {
299 			iptr++;
300 		}
301 
302 		if (*iptr == '0') {
303 			zero_pad = 1;
304 			iptr++;
305 		}
306 
307 		width = 0;
308 		while (*iptr && bcm_isdigit(*iptr)) {
309 			width += (*iptr - '0');
310 			iptr++;
311 			if (bcm_isdigit(*iptr))
312 				width *= 10;
313 		}
314 		if (*iptr == '.') {
315 			iptr++;
316 			width2 = 0;
317 			while (*iptr && bcm_isdigit(*iptr)) {
318 				width2 += (*iptr - '0');
319 				iptr++;
320 				if (bcm_isdigit(*iptr)) width2 *= 10;
321 			}
322 		}
323 
324 		islong = 0;
325 		if (*iptr == 'l') {
326 			islong++;
327 			iptr++;
328 			if (*iptr == 'l') {
329 				++islong;
330 				++iptr;
331 			}
332 		}
333 
334 		switch (*iptr) {
335 		case 's':
336 			tmpptr = va_arg(ap, const char *);
337 			if (!tmpptr)
338 				tmpptr = "(null)";
339 			if ((width == 0) & (width2 == 0)) {
340 				while (*tmpptr) {
341 					if (optr <= end)
342 						*optr = *tmpptr;
343 					++optr;
344 					++tmpptr;
345 				}
346 				break;
347 			}
348 			while (width && *tmpptr) {
349 				if (optr <= end)
350 					*optr = *tmpptr;
351 				++optr;
352 				++tmpptr;
353 				width--;
354 			}
355 			while (width) {
356 				if (optr <= end)
357 					*optr = ' ';
358 				++optr;
359 				width--;
360 			}
361 			break;
362 		case 'd':
363 		case 'i':
364 			if (!islong) {
365 				i = va_arg(ap, int);
366 				if (i < 0) {
367 					if (optr <= end)
368 						*optr = '-';
369 					++optr;
370 					i = -i;
371 				}
372 				optr += __atox(optr, end, i, 10, width, hex_upper, zero_pad);
373 			} else {
374 				li = va_arg(ap, long int);
375 				if (li < 0) {
376 					if (optr <= end)
377 						*optr = '-';
378 					++optr;
379 					li = -li;
380 				}
381 				optr += __atolx(optr, end, li, 10, width, hex_upper, zero_pad);
382 			}
383 			break;
384 		case 'u':
385 			if (!islong) {
386 				x = va_arg(ap, unsigned int);
387 				optr += __atox(optr, end, x, 10, width, hex_upper, zero_pad);
388 			} else {
389 				ul = va_arg(ap, unsigned long);
390 				optr += __atolx(optr, end, ul, 10, width, hex_upper, zero_pad);
391 			}
392 			break;
393 		case 'X':
394 		case 'x':
395 			if (hashash) {
396 				*optr++ = '0';
397 				*optr++ = *iptr;
398 			}
399 			if (!islong) {
400 				x = va_arg(ap, unsigned int);
401 				optr += __atox(optr, end, x, 16, width,
402 						(*iptr == 'X') ? hex_upper : hex_lower, zero_pad);
403 			} else {
404 				ul = va_arg(ap, unsigned long);
405 				optr += __atolx(optr, end, ul, 16, width,
406 						(*iptr == 'X') ? hex_upper : hex_lower, zero_pad);
407 			}
408 			break;
409 		case 'p':
410 		case 'P':
411 			x = va_arg(ap, unsigned int);
412 			optr += __atox(optr, end, x, 16, 8,
413 			               (*iptr == 'P') ? hex_upper : hex_lower, zero_pad);
414 			break;
415 		case 'c':
416 			x = va_arg(ap, int);
417 			if (optr <= end)
418 				*optr = x & 0xff;
419 			optr++;
420 			break;
421 
422 		default:
423 			if (optr <= end)
424 				*optr = *iptr;
425 			optr++;
426 			break;
427 		}
428 		iptr++;
429 	}
430 
431 	if (optr <= end) {
432 		*optr = '\0';
433 		return (int)(optr - buf);
434 	} else {
435 		*end = '\0';
436 		return (int)(end - buf);
437 	}
438 }
439 
440 int
BCMPOSTTRAPFN(snprintf)441 BCMPOSTTRAPFN(snprintf)(char *buf, size_t bufsize, const char *fmt, ...)
442 {
443 	va_list		ap;
444 	int			r;
445 
446 	if (FWSIGN_ENAB()) {
447 		return 0;
448 	}
449 
450 	va_start(ap, fmt);
451 	r = vsnprintf(buf, bufsize, fmt, ap);
452 	va_end(ap);
453 
454 	return r;
455 }
456 #endif	/* !BCMROMOFFLOAD_EXCLUDE_STDLIB_FUNCS */
457 
458 #endif /* BCMSTDLIB_WIN32_APP */
459 
460 #ifndef BCMSTDLIB_SNPRINTF_ONLY
461 int
BCMPOSTTRAPFN(vsprintf)462 BCMPOSTTRAPFN(vsprintf)(char *buf, const char *fmt, va_list ap)
463 {
464 	if (FWSIGN_ENAB()) {
465 		return 0;
466 	}
467 	return (vsnprintf(buf, INT_MAX, fmt, ap));
468 }
469 
470 int
BCMPOSTTRAPFN(sprintf)471 BCMPOSTTRAPFN(sprintf)(char *buf, const char *fmt, ...)
472 {
473 	va_list ap;
474 	int count;
475 
476 	if (FWSIGN_ENAB()) {
477 		return 0;
478 	}
479 
480 	va_start(ap, fmt);
481 	count = vsprintf(buf, fmt, ap);
482 	va_end(ap);
483 
484 	return count;
485 }
486 
487 #if !defined(EFI) || !defined(COMPILER_INTRINSICS_LIB)
488 void *
memmove(void * dest,const void * src,size_t n)489 memmove(void *dest, const void *src, size_t n)
490 {
491 	/* only use memcpy if there is no overlap. otherwise copy each byte in a safe sequence */
492 	if (((const char *)src >= (char *)dest + n) || ((const char *)src + n <= (char *)dest)) {
493 		return memcpy(dest, src, n);
494 	}
495 
496 	/* Overlapping copy forward or backward */
497 	if (src < dest) {
498 		unsigned char *d = (unsigned char *)dest + (n - 1);
499 		const unsigned char *s = (const unsigned char *)src + (n - 1);
500 		while (n) {
501 			*d-- = *s--;
502 			n--;
503 		}
504 	} else if (src > dest) {
505 		unsigned char *d = (unsigned char *)dest;
506 		const unsigned char *s = (const unsigned char *)src;
507 		while (n) {
508 			*d++ = *s++;
509 			n--;
510 		}
511 	}
512 
513 	return dest;
514 }
515 #endif /* !EFI || !COMPILER_INTRINSICS_LIB */
516 
517 #ifndef EFI
518 int
memcmp(const void * s1,const void * s2,size_t n)519 memcmp(const void *s1, const void *s2, size_t n)
520 {
521 	const unsigned char *ss1;
522 	const unsigned char *ss2;
523 
524 	ss1 = (const unsigned char *)s1;
525 	ss2 = (const unsigned char *)s2;
526 
527 	while (n) {
528 		if (*ss1 < *ss2)
529 			return -1;
530 		if (*ss1 > *ss2)
531 			return 1;
532 		ss1++;
533 		ss2++;
534 		n--;
535 	}
536 
537 	return 0;
538 }
539 
540 /* Skip over functions that are being used from DriverLibrary to save space */
541 char *
strncpy(char * dest,const char * src,size_t n)542 strncpy(char *dest, const char *src, size_t n)
543 {
544 	char *endp;
545 	char *p;
546 
547 	p = dest;
548 	endp = p + n;
549 
550 	while (p != endp && (*p++ = *src++) != '\0')
551 		;
552 
553 	/* zero fill remainder */
554 	bzero(p, (endp - p));
555 
556 	return dest;
557 }
558 
559 size_t
BCMPOSTTRAPFN(strlen)560 BCMPOSTTRAPFN(strlen)(const char *s)
561 {
562 	size_t n = 0;
563 
564 	while (*s) {
565 		s++;
566 		n++;
567 	}
568 
569 	return n;
570 }
571 
572 int
BCMPOSTTRAPFN(strcmp)573 BCMPOSTTRAPFN(strcmp)(const char *s1, const char *s2)
574 {
575 	while (*s2 && *s1) {
576 		if (*s1 < *s2)
577 			return -1;
578 		if (*s1 > *s2)
579 			return 1;
580 		s1++;
581 		s2++;
582 	}
583 
584 	if (*s1 && !*s2)
585 		return 1;
586 	if (!*s1 && *s2)
587 		return -1;
588 	return 0;
589 }
590 #endif /* EFI */
591 
592 int
strncmp(const char * s1,const char * s2,size_t n)593 strncmp(const char *s1, const char *s2, size_t n)
594 {
595 	while (*s2 && *s1 && n) {
596 		if (*s1 < *s2)
597 			return -1;
598 		if (*s1 > *s2)
599 			return 1;
600 		s1++;
601 		s2++;
602 		n--;
603 	}
604 
605 	if (!n)
606 		return 0;
607 	if (*s1 && !*s2)
608 		return 1;
609 	if (!*s1 && *s2)
610 		return -1;
611 	return 0;
612 }
613 
614 char *
strchr(const char * str,int c)615 strchr(const char *str, int c)
616 {
617 	const char *x = str;
618 
619 	while (*x != (char)c) {
620 		if (*x++ == '\0')
621 			return (NULL);
622 	}
623 
624 	return DISCARD_QUAL(x, char);
625 }
626 
627 char *
strrchr(const char * str,int c)628 strrchr(const char *str, int c)
629 {
630 	const char *save = NULL;
631 
632 	do {
633 		if (*str == (char)c)
634 			save = str;
635 	} while (*str++ != '\0');
636 
637 	return DISCARD_QUAL(save, char);
638 }
639 
640 /* Skip over functions that are being used from DriverLibrary to save space */
641 #ifndef EFI
642 char *
strstr(const char * s,const char * substr)643 strstr(const char *s, const char *substr)
644 {
645 	int substr_len = strlen(substr);
646 
647 	for (; *s; s++)
648 		if (strncmp(s, substr, substr_len) == 0)
649 			return DISCARD_QUAL(s, char);
650 
651 	return NULL;
652 }
653 #endif /* EFI */
654 
655 size_t
strspn(const char * s,const char * accept)656 strspn(const char *s, const char *accept)
657 {
658 	uint count = 0;
659 
660 	while (s[count] && strchr(accept, s[count]))
661 		count++;
662 
663 	return count;
664 }
665 
666 size_t
strcspn(const char * s,const char * reject)667 strcspn(const char *s, const char *reject)
668 {
669 	uint count = 0;
670 
671 	while (s[count] && !strchr(reject, s[count]))
672 		count++;
673 
674 	return count;
675 }
676 
677 void *
memchr(const void * s,int c,size_t n)678 memchr(const void *s, int c, size_t n)
679 {
680 	if (n != 0) {
681 		const unsigned char *ptr = s;
682 
683 		do {
684 			if (*ptr == (unsigned char)c)
685 				return DISCARD_QUAL(ptr, void);
686 			ptr++;
687 			n--;
688 		} while (n != 0);
689 	}
690 	return NULL;
691 }
692 
693 unsigned long
strtoul(const char * cp,char ** endp,int base)694 strtoul(const char *cp, char **endp, int base)
695 {
696 	ulong result, value;
697 	bool minus;
698 
699 	minus = FALSE;
700 
701 	while (bcm_isspace(*cp))
702 		cp++;
703 
704 	if (cp[0] == '+')
705 		cp++;
706 	else if (cp[0] == '-') {
707 		minus = TRUE;
708 		cp++;
709 	}
710 
711 	if (base == 0) {
712 		if (cp[0] == '0') {
713 			if ((cp[1] == 'x') || (cp[1] == 'X')) {
714 				base = 16;
715 				cp = &cp[2];
716 			} else {
717 				base = 8;
718 				cp = &cp[1];
719 			}
720 		} else
721 			base = 10;
722 	} else if (base == 16 && (cp[0] == '0') && ((cp[1] == 'x') || (cp[1] == 'X'))) {
723 		cp = &cp[2];
724 	}
725 
726 	result = 0;
727 
728 	while (bcm_isxdigit(*cp) &&
729 	       (value = bcm_isdigit(*cp) ? *cp - '0' : bcm_toupper(*cp) - 'A' + 10) <
730 	       (ulong) base) {
731 		result = result * base + value;
732 		cp++;
733 	}
734 
735 	if (minus)
736 		result = (ulong)(result * -1);
737 
738 	if (endp)
739 		*endp = DISCARD_QUAL(cp, char);
740 
741 	return (result);
742 }
743 
744 #ifdef EFI
745 int
putchar(int c)746 putchar(int c)
747 {
748 	return putc(c, stdout);
749 }
750 
751 int
puts(const char * s)752 puts(const char *s)
753 {
754 	char c;
755 
756 	while ((c = *s++))
757 		putchar(c);
758 
759 	putchar('\n');
760 
761 	return 0;
762 }
763 
764 #else /* !EFI */
765 
766 /* memset is not in ROM offload because it is used directly by the compiler in
767  * structure assignments/character array initialization with "".
768  */
769 void *
BCMPOSTTRAPFN(memset)770 BCMPOSTTRAPFN(memset)(void *dest, int c, size_t n)
771 {
772 	uint32 w, *dw;
773 	unsigned char *d;
774 
775 	dw = (uint32 *)dest;
776 
777 	/* 8 min because we have to create w */
778 	if ((n >= 8) && (((uintptr)dest & 3) == 0)) {
779 		if (c == 0)
780 			w = 0;
781 		else {
782 			unsigned char ch;
783 
784 			ch = (unsigned char)(c & 0xff);
785 			w = (ch << 8) | ch;
786 			w |= w << 16;
787 		}
788 		while (n >= 4) {
789 			*dw++ = w;
790 			n -= 4;
791 		}
792 	}
793 	d = (unsigned char *)dw;
794 
795 	while (n) {
796 		*d++ = (unsigned char)c;
797 		n--;
798 	}
799 
800 	return dest;
801 }
802 
803 /* memcpy is not in ROM offload because it is used directly by the compiler in
804  * structure assignments.
805  */
806 #if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7A__)
807 void *
BCMPOSTTRAPFN(memcpy)808 BCMPOSTTRAPFN(memcpy)(void *dest, const void *src, size_t n)
809 {
810 	uint32 *dw;
811 	const uint32 *sw;
812 	unsigned char *d;
813 	const unsigned char *s;
814 
815 	sw = (const uint32 *)src;
816 	dw = (uint32 *)dest;
817 
818 	if (n >= 4 && ((uintptr)src & 3) == ((uintptr)dest & 3)) {
819 		uint32 t1, t2, t3, t4, t5, t6, t7, t8;
820 		int i = (4 - ((uintptr)src & 3)) % 4;
821 
822 		n -= i;
823 
824 		d = (unsigned char *)dw;
825 		s = (const unsigned char *)sw;
826 		while (i--) {
827 			*d++ = *s++;
828 		}
829 		sw = (const uint32 *)s;
830 		dw = (uint32 *)d;
831 
832 		if (n >= 32) {
833 			const uint32 *sfinal = (const uint32 *)((const uint8 *)sw + (n & ~31));
834 
835 			asm volatile("\n1:\t"
836 				     "ldmia.w\t%0!, {%3, %4, %5, %6, %7, %8, %9, %10}\n\t"
837 				     "stmia.w\t%1!, {%3, %4, %5, %6, %7, %8, %9, %10}\n\t"
838 				     "cmp\t%2, %0\n\t"
839 				     "bhi.n\t1b\n\t"
840 				     : "=r" (sw), "=r" (dw), "=r" (sfinal), "=r" (t1), "=r" (t2),
841 				     "=r" (t3), "=r" (t4), "=r" (t5), "=r" (t6), "=r" (t7),
842 				     "=r" (t8)
843 				     : "0" (sw), "1" (dw), "2" (sfinal));
844 
845 			n %= 32;
846 		}
847 
848 		/* Copy the remaining words */
849 		switch (n / 4) {
850 		case 0:
851 			break;
852 		case 1:
853 			asm volatile("ldr\t%2, [%0]\n\t"
854 			             "str\t%2, [%1]\n\t"
855 			             "adds\t%0, #4\n\t"
856 			             "adds\t%1, #4\n\t"
857 			             : "=r" (sw), "=r" (dw), "=r" (t1)
858 			             : "0" (sw), "1" (dw));
859 			break;
860 		case 2:
861 			asm volatile("ldmia.w\t%0!, {%2, %3}\n\t"
862 			             "stmia.w\t%1!, {%2, %3}\n\t"
863 			             : "=r" (sw), "=r" (dw), "=r" (t1), "=r" (t2)
864 			             : "0" (sw), "1" (dw));
865 			break;
866 		case 3:
867 			asm volatile("ldmia.w\t%0!, {%2, %3, %4}\n\t"
868 			             "stmia.w\t%1!, {%2, %3, %4}\n\t"
869 			             : "=r" (sw), "=r" (dw), "=r" (t1), "=r" (t2),
870 			             "=r" (t3)
871 			             : "0" (sw), "1" (dw));
872 			break;
873 		case 4:
874 			asm volatile("ldmia.w\t%0!, {%2, %3, %4, %5}\n\t"
875 			             "stmia.w\t%1!, {%2, %3, %4, %5}\n\t"
876 			             : "=r" (sw), "=r" (dw), "=r" (t1), "=r" (t2),
877 			             "=r" (t3), "=r" (t4)
878 			             : "0" (sw), "1" (dw));
879 			break;
880 		case 5:
881 			asm volatile(
882 				     "ldmia.w\t%0!, {%2, %3, %4, %5, %6}\n\t"
883 			             "stmia.w\t%1!, {%2, %3, %4, %5, %6}\n\t"
884 			             : "=r" (sw), "=r" (dw), "=r" (t1), "=r" (t2),
885 			             "=r" (t3), "=r" (t4), "=r" (t5)
886 			             : "0" (sw), "1" (dw));
887 			break;
888 		case 6:
889 			asm volatile(
890 				     "ldmia.w\t%0!, {%2, %3, %4, %5, %6, %7}\n\t"
891 			             "stmia.w\t%1!, {%2, %3, %4, %5, %6, %7}\n\t"
892 			             : "=r" (sw), "=r" (dw), "=r" (t1), "=r" (t2),
893 			             "=r" (t3), "=r" (t4), "=r" (t5), "=r" (t6)
894 			             : "0" (sw), "1" (dw));
895 			break;
896 		case 7:
897 			asm volatile(
898 				     "ldmia.w\t%0!, {%2, %3, %4, %5, %6, %8, %7}\n\t"
899 			             "stmia.w\t%1!, {%2, %3, %4, %5, %6, %8, %7}\n\t"
900 			             : "=r" (sw), "=r" (dw), "=r" (t1), "=r" (t2),
901 			             "=r" (t3), "=r" (t4), "=r" (t5), "=r" (t6),
902 			             "=r" (t7)
903 			             : "0" (sw), "1" (dw));
904 			break;
905 		default:
906 			ASSERT(0);
907 			break;
908 		}
909 		n = n % 4;
910 	}
911 
912 	/* Copy the remaining bytes */
913 	d = (unsigned char *)dw;
914 	s = (const unsigned char *)sw;
915 	while (n--) {
916 		*d++ = *s++;
917 	}
918 
919 	return dest;
920 }
921 
922 #ifdef __clang__
923 /* TODO: remove once toolchain builtin libraries are available */
924 /* simulate compiler builtins */
925 
926 /* not aligned */
927 void *__aeabi_memcpy(void *dest, const void *src, size_t n);
928 void *
__aeabi_memcpy(void * dest,const void * src,size_t n)929 __aeabi_memcpy(void *dest, const void *src, size_t n)
930 {
931 	return memcpy(dest, src, n);
932 }
933 
934 /* 4 byte aligned */
935 void *__aeabi_memcpy4(void *dest, const void *src, size_t n);
936 void *
__aeabi_memcpy4(void * dest,const void * src,size_t n)937 __aeabi_memcpy4(void *dest, const void *src, size_t n)
938 {
939 	return memcpy(dest, src, n);
940 }
941 
942 /* 8 byte aligned */
943 void *__aeabi_memcpy8(void *dest, const void *src, size_t n);
944 void *
__aeabi_memcpy8(void * dest,const void * src,size_t n)945 __aeabi_memcpy8(void *dest, const void *src, size_t n)
946 {
947 	return memcpy(dest, src, n);
948 }
949 
950 /* 8 byte aligned */
951 void *__aeabi_memclr8(void *dest, size_t n);
952 void *
__aeabi_memclr8(void * dest,size_t n)953 __aeabi_memclr8(void *dest, size_t n)
954 {
955 	return memset(dest, 0, n);
956 }
957 #endif /* __clang__ */
958 #else
959 void *
memcpy(void * dest,const void * src,size_t n)960 memcpy(void *dest, const void *src, size_t n)
961 {
962 	uint32 *dw;
963 	const uint32 *sw;
964 	unsigned char *d;
965 	const unsigned char *s;
966 
967 	sw = (const uint32 *)src;
968 	dw = (uint32 *)dest;
969 
970 	if ((n >= 4) && (((uintptr)src & 3) == ((uintptr)dest & 3))) {
971 		int i = (4 - ((uintptr)src & 3)) % 4;
972 		n -= i;
973 		d = (unsigned char *)dw;
974 		s = (const unsigned char *)sw;
975 		while (i--) {
976 			*d++ = *s++;
977 		}
978 
979 		sw = (const uint32 *)s;
980 		dw = (uint32 *)d;
981 		while (n >= 4) {
982 			*dw++ = *sw++;
983 			n -= 4;
984 		}
985 	}
986 	d = (unsigned char *)dw;
987 	s = (const unsigned char *)sw;
988 	while (n--) {
989 		*d++ = *s++;
990 	}
991 
992 	return dest;
993 }
994 #endif /* defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7A__) */
995 #endif /* EFI */
996 
997 /* a hook to send printf output to the host */
998 static printf_sendup_output_fn_t g_printf_sendup_output_fn = NULL;
999 static void *g_printf_sendup_output_ctx = NULL;
1000 
1001 #ifdef DONGLEBUILD
1002 static bool _rodata_overwritten = FALSE;
1003 
1004 /* Ensure this string is not const. */
1005 CONST char BCMPOST_TRAP_RODATA(warn_str)[] = "RO overwritten %p\n";
1006 CONST char BCMPOST_TRAP_RODATA(time_str)[] = "%06u.%03u ";
1007 #endif /* DONGLEBUILD */
1008 
1009 void
printf_set_sendup_output_fn(printf_sendup_output_fn_t fn,void * ctx)1010 printf_set_sendup_output_fn(printf_sendup_output_fn_t fn, void *ctx)
1011 {
1012 	g_printf_sendup_output_fn = fn;
1013 	g_printf_sendup_output_ctx = ctx;
1014 }
1015 
1016 #ifdef DONGLEBUILD
1017 void
BCMPOSTTRAPFN(printf_set_rodata_invalid)1018 BCMPOSTTRAPFN(printf_set_rodata_invalid)(void)
1019 {
1020 	_rodata_overwritten = TRUE;
1021 }
1022 
1023 bool
printf_get_rodata_invalid(void)1024 printf_get_rodata_invalid(void)
1025 {
1026 	return (_rodata_overwritten);
1027 }
1028 #endif /* DONGLEBUILD */
1029 
1030 /* Include printf if it has already not been defined as NULL */
1031 #ifndef printf
1032 static bool last_nl = FALSE;
1033 int
BCMPOSTTRAPFN(printf)1034 BCMPOSTTRAPFN(printf)(const char *fmt, ...)
1035 {
1036 	va_list ap;
1037 	int count = 0, i;
1038 	char buffer[PRINTF_BUFLEN + 1];
1039 
1040 	if (FWSIGN_ENAB()) {
1041 		return 0;
1042 	}
1043 
1044 	if (!printf_lock())
1045 		return 0;
1046 
1047 #ifdef DONGLEBUILD
1048 	if (_rodata_overwritten == TRUE) {
1049 		/* Regular printf will be garbage if ROdata is overwritten. In that case,
1050 		 * print the caller address.
1051 		 */
1052 		_rodata_overwritten = FALSE;
1053 		count = printf(warn_str, CALL_SITE);
1054 		_rodata_overwritten = TRUE;
1055 		return count;
1056 	}
1057 
1058 	if (last_nl) {
1059 		/* add the dongle ref time */
1060 		uint32 dongle_time_ms = hnd_get_reftime_ms();
1061 		count = sprintf(buffer, time_str, dongle_time_ms / 1000, dongle_time_ms % 1000);
1062 	}
1063 #endif /* DONGLEBUILD */
1064 
1065 	va_start(ap, fmt);
1066 	count += vsnprintf(buffer + count, sizeof(buffer) - count, fmt, ap);
1067 	va_end(ap);
1068 
1069 	for (i = 0; i < count; i++) {
1070 		putchar(buffer[i]);
1071 
1072 		/* EFI environment requires CR\LF in a printf, etc.
1073 		 * so unless the string has \r\n, it will not execute CR
1074 		 * So force it!
1075 		 */
1076 #ifdef EFI
1077 		if (buffer[i] == '\n')
1078 			putchar('\r');
1079 #endif
1080 	}
1081 
1082 	/* send the output up to the host */
1083 	if (g_printf_sendup_output_fn != NULL) {
1084 		g_printf_sendup_output_fn(g_printf_sendup_output_ctx, buffer, count);
1085 	}
1086 
1087 	if (buffer[count - 1] == '\n')
1088 		last_nl = TRUE;
1089 	else
1090 		last_nl = FALSE;
1091 
1092 	printf_unlock();
1093 
1094 	return count;
1095 }
1096 #endif /* printf */
1097 
1098 #if !defined(_WIN32) && !defined(EFI)
1099 int
fputs(const char * s,FILE * stream)1100 fputs(const char *s, FILE *stream /* UNUSED */)
1101 {
1102 	char c;
1103 
1104 	UNUSED_PARAMETER(stream);
1105 	while ((c = *s++))
1106 		putchar(c);
1107 	return 0;
1108 }
1109 
1110 int
puts(const char * s)1111 puts(const char *s)
1112 {
1113 	fputs(s, stdout);
1114 	putchar('\n');
1115 	return 0;
1116 }
1117 
1118 int
fputc(int c,FILE * stream)1119 fputc(int c, FILE *stream)
1120 {
1121 	return putc(c, stream);
1122 }
1123 
1124 unsigned long
rand(void)1125 rand(void)
1126 {
1127 	static unsigned long seed = 1;
1128 	long x, hi, lo, t;
1129 
1130 	x = seed;
1131 	hi = x / 127773;
1132 	lo = x % 127773;
1133 	t = 16807 * lo - 2836 * hi;
1134 	if (t <= 0) t += 0x7fffffff;
1135 	seed = t;
1136 	return t;
1137 }
1138 #endif /* !_WIN32 && !EFI */
1139 
1140 #endif /* BCMSTDLIB_SNPRINTF_ONLY */
1141 
1142 #if !defined(_WIN32) || defined(EFI)
1143 size_t
strnlen(const char * s,size_t maxlen)1144 strnlen(const char *s, size_t maxlen)
1145 {
1146 	const char *b = s;
1147 	const char *e = s + maxlen;
1148 
1149 	while (s < e && *s) {
1150 		s++;
1151 	}
1152 
1153 	return s - b;
1154 }
1155 #endif /* !_WIN32 || EFI */
1156 
1157 /* FORTIFY_SOURCE: Implementation of compiler built-in functions for C standard library functions
1158  * that provide run-time buffer overflow detection.
1159  */
1160 #if defined(BCM_FORTIFY_SOURCE)
1161 
1162 void*
__memcpy_chk(void * dest,const void * src,size_t n,size_t destsz)1163 __memcpy_chk(void *dest, const void *src, size_t n, size_t destsz)
1164 {
1165 	if (memcpy_s(dest, destsz, src, n) != 0) {
1166 		OSL_SYS_HALT();
1167 	}
1168 
1169 	return (dest);
1170 }
1171 
1172 void *
__memmove_chk(void * dest,const void * src,size_t n,size_t destsz)1173 __memmove_chk(void *dest, const void *src, size_t n, size_t destsz)
1174 {
1175 	if (memmove_s(dest, destsz, src, n) != 0) {
1176 		OSL_SYS_HALT();
1177 	}
1178 
1179 	return (dest);
1180 }
1181 
1182 void *
__memset_chk(void * dest,int c,size_t n,size_t destsz)1183 __memset_chk(void *dest, int c, size_t n, size_t destsz)
1184 {
1185 	if (memset_s(dest, destsz, c, n) != 0) {
1186 		OSL_SYS_HALT();
1187 	}
1188 
1189 	return (dest);
1190 }
1191 
1192 int
__snprintf_chk(char * str,size_t n,int flag,size_t destsz,const char * fmt,...)1193 __snprintf_chk(char *str, size_t n, int flag, size_t destsz, const char *fmt, ...)
1194 {
1195 	va_list arg;
1196 	int rc;
1197 
1198 	if (n > destsz) {
1199 		OSL_SYS_HALT();
1200 	}
1201 
1202 	va_start(arg, fmt);
1203 	rc = vsnprintf(str, n, fmt, arg);
1204 	va_end(arg);
1205 
1206 	return (rc);
1207 }
1208 
1209 int
__vsnprintf_chk(char * str,size_t n,int flags,size_t destsz,const char * fmt,va_list ap)1210 __vsnprintf_chk(char *str, size_t n, int flags, size_t destsz, const char *fmt, va_list ap)
1211 {
1212 	if (n > destsz) {
1213 		OSL_SYS_HALT();
1214 	}
1215 
1216 	return (vsnprintf(str, n, fmt, ap));
1217 }
1218 
1219 char *
__strncpy_chk(char * dest,const char * src,size_t n,size_t destsz)1220 __strncpy_chk(char *dest, const char *src, size_t n, size_t destsz)
1221 {
1222 	if (n > destsz) {
1223 		OSL_SYS_HALT();
1224 	}
1225 
1226 	return (strncpy(dest, src, n));
1227 }
1228 #endif	/* BCM_FORTIFY_SOURCE */
1229 
1230 /* Provide stub implementations for xxx_s() APIs that are remapped to compiler builtins.
1231  * This allows the target to link.
1232  *
1233  * This is only intended as a compile-time test, and should be used by compile-only targets.
1234  */
1235 #if defined(BCM_STDLIB_S_BUILTINS_TEST)
1236 #undef strcpy
1237 char* strcpy(char *dest, const char *src);
1238 char*
strcpy(char * dest,const char * src)1239 strcpy(char *dest, const char *src)
1240 {
1241 	return (NULL);
1242 }
1243 
1244 #undef strcat
1245 char* strcat(char *dest, const char *src);
1246 char*
strcat(char * dest,const char * src)1247 strcat(char *dest, const char *src)
1248 {
1249 	return (NULL);
1250 }
1251 #endif /* BCM_STDLIB_S_BUILTINS_TEST */
1252