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