aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorAmbroise Vincent <ambroise.vincent@arm.com>2019-02-11 13:34:41 +0000
committerAmbroise Vincent <ambroise.vincent@arm.com>2019-03-04 11:17:40 +0000
commit4128f9f887ed0ef0c511d2299c75ca71335b3cf1 (patch)
tree9c1624075ae2a7af810df40d527d46195d55ee26 /lib
parent2eafdf2c74cf00b9bc3dbeccac794a433acc0c16 (diff)
downloadtf-a-tests-4128f9f887ed0ef0c511d2299c75ca71335b3cf1.tar.gz
libc: Import from TF-A
Based on arm-trusted-firware commit 873e394b3bf93214a441f9f98237b58fbbea55aa Change-Id: I510e092f2b9ff333e9461bdde8d80ed1fab1460c Signed-off-by: Ambroise Vincent <ambroise.vincent@arm.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/libc/aarch64/setjmp.S61
-rw-r--r--lib/libc/abort.c15
-rw-r--r--lib/libc/assert.c43
-rw-r--r--lib/libc/exit.c26
-rw-r--r--lib/libc/libc.mk34
-rw-r--r--lib/libc/memchr.c20
-rw-r--r--lib/libc/memcmp.c24
-rw-r--r--lib/libc/memcpy.c18
-rw-r--r--lib/libc/memmove.c31
-rw-r--r--lib/libc/memset.c17
-rw-r--r--lib/libc/printf.c197
-rw-r--r--lib/libc/putchar.c20
-rw-r--r--lib/libc/puts.c24
-rw-r--r--lib/libc/snprintf.c143
-rw-r--r--lib/libc/strchr.c53
-rw-r--r--lib/libc/strcmp.c52
-rw-r--r--lib/libc/strlcpy.c52
-rw-r--r--lib/libc/strlen.c17
-rw-r--r--lib/libc/strncmp.c53
-rw-r--r--lib/libc/strnlen.c46
-rw-r--r--lib/libc/strrchr.c49
21 files changed, 995 insertions, 0 deletions
diff --git a/lib/libc/aarch64/setjmp.S b/lib/libc/aarch64/setjmp.S
new file mode 100644
index 00000000..9d9eb49b
--- /dev/null
+++ b/lib/libc/aarch64/setjmp.S
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <asm_macros.S>
+#include <assert_macros.S>
+#include <setjmp.h>
+
+ .globl setjmp
+ .globl longjmp
+
+/*
+ * int setjmp(jmp_buf env);
+ */
+func setjmp
+ mov x7, sp
+
+ stp x19, x20, [x0, #JMP_CTX_X19]
+ stp x21, x22, [x0, #JMP_CTX_X21]
+ stp x23, x24, [x0, #JMP_CTX_X23]
+ stp x25, x26, [x0, #JMP_CTX_X25]
+ stp x27, x28, [x0, #JMP_CTX_X27]
+ stp x29, x30, [x0, #JMP_CTX_X29]
+ stp x7, xzr, [x0, #JMP_CTX_SP]
+
+ mov x0, #0
+ ret
+endfunc setjmp
+
+
+/*
+ * void longjmp(jmp_buf env, int val);
+ */
+func longjmp
+ ldp x7, xzr, [x0, #JMP_CTX_SP]
+
+#if ENABLE_ASSERTIONS
+ /*
+ * Since we're unwinding the stack, assert that the stack being reset to
+ * is shallower.
+ */
+ mov x19, sp
+ cmp x7, x19
+ ASM_ASSERT(ge)
+#endif
+
+ ldp x19, x20, [x0, #JMP_CTX_X19]
+ ldp x21, x22, [x0, #JMP_CTX_X21]
+ ldp x23, x24, [x0, #JMP_CTX_X23]
+ ldp x25, x26, [x0, #JMP_CTX_X25]
+ ldp x27, x28, [x0, #JMP_CTX_X27]
+ ldp x29, x30, [x0, #JMP_CTX_X29]
+
+ mov sp, x7
+
+ ands x0, x1, x1 /* Move val to x0 and set flags */
+ cinc x0, x0, eq /* If val is 0, return 1 */
+ ret
+endfunc longjmp
diff --git a/lib/libc/abort.c b/lib/libc/abort.c
new file mode 100644
index 00000000..432b1d07
--- /dev/null
+++ b/lib/libc/abort.c
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdlib.h>
+
+#include <common/debug.h>
+
+void abort(void)
+{
+ ERROR("ABORT\n");
+ panic();
+}
diff --git a/lib/libc/assert.c b/lib/libc/assert.c
new file mode 100644
index 00000000..60f1a866
--- /dev/null
+++ b/lib/libc/assert.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <cdefs.h>
+#include <stdio.h>
+
+#include <common/debug.h>
+#include <drivers/console.h>
+#include <plat/common/platform.h>
+
+/*
+ * Only print the output if PLAT_LOG_LEVEL_ASSERT is higher or equal to
+ * LOG_LEVEL_INFO, which is the default value for builds with DEBUG=1.
+ */
+
+#if PLAT_LOG_LEVEL_ASSERT >= LOG_LEVEL_VERBOSE
+void __assert(const char *file, unsigned int line, const char *assertion)
+{
+ printf("ASSERT: %s:%d:%s\n", file, line, assertion);
+ backtrace("assert");
+ (void)console_flush();
+ plat_panic_handler();
+}
+#elif PLAT_LOG_LEVEL_ASSERT >= LOG_LEVEL_INFO
+void __assert(const char *file, unsigned int line)
+{
+ printf("ASSERT: %s:%d\n", file, line);
+ backtrace("assert");
+ (void)console_flush();
+ plat_panic_handler();
+}
+#else
+void __assert(void)
+{
+ backtrace("assert");
+ (void)console_flush();
+ plat_panic_handler();
+}
+#endif
diff --git a/lib/libc/exit.c b/lib/libc/exit.c
new file mode 100644
index 00000000..f4ffe27c
--- /dev/null
+++ b/lib/libc/exit.c
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdlib.h>
+
+static void (*exitfun)(void);
+
+void exit(int status)
+{
+ if (exitfun != NULL)
+ (*exitfun)();
+ for (;;)
+ ;
+}
+
+int atexit(void (*fun)(void))
+{
+ if (exitfun != NULL)
+ return -1;
+ exitfun = fun;
+
+ return 0;
+}
diff --git a/lib/libc/libc.mk b/lib/libc/libc.mk
new file mode 100644
index 00000000..e1b5560f
--- /dev/null
+++ b/lib/libc/libc.mk
@@ -0,0 +1,34 @@
+#
+# Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+LIBC_SRCS := $(addprefix lib/libc/, \
+ abort.c \
+ assert.c \
+ exit.c \
+ memchr.c \
+ memcmp.c \
+ memcpy.c \
+ memmove.c \
+ memset.c \
+ printf.c \
+ putchar.c \
+ puts.c \
+ snprintf.c \
+ strchr.c \
+ strcmp.c \
+ strlcpy.c \
+ strlen.c \
+ strncmp.c \
+ strnlen.c \
+ strrchr.c)
+
+ifeq (${ARCH},aarch64)
+LIBC_SRCS += $(addprefix lib/libc/aarch64/, \
+ setjmp.S)
+endif
+
+INCLUDES += -Iinclude/lib/libc \
+ -Iinclude/lib/libc/$(ARCH) \
diff --git a/lib/libc/memchr.c b/lib/libc/memchr.c
new file mode 100644
index 00000000..2eba47c9
--- /dev/null
+++ b/lib/libc/memchr.c
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stddef.h>
+
+void *memchr(const void *src, int c, size_t len)
+{
+ const char *s = src;
+
+ while (len--) {
+ if (*s == c)
+ return (void *) s;
+ s++;
+ }
+
+ return NULL;
+}
diff --git a/lib/libc/memcmp.c b/lib/libc/memcmp.c
new file mode 100644
index 00000000..a4c798b0
--- /dev/null
+++ b/lib/libc/memcmp.c
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stddef.h>
+
+int memcmp(const void *s1, const void *s2, size_t len)
+{
+ const unsigned char *s = s1;
+ const unsigned char *d = s2;
+ unsigned char sc;
+ unsigned char dc;
+
+ while (len--) {
+ sc = *s++;
+ dc = *d++;
+ if (sc - dc)
+ return (sc - dc);
+ }
+
+ return 0;
+}
diff --git a/lib/libc/memcpy.c b/lib/libc/memcpy.c
new file mode 100644
index 00000000..fc0c9fe8
--- /dev/null
+++ b/lib/libc/memcpy.c
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stddef.h>
+
+void *memcpy(void *dst, const void *src, size_t len)
+{
+ const char *s = src;
+ char *d = dst;
+
+ while (len--)
+ *d++ = *s++;
+
+ return dst;
+}
diff --git a/lib/libc/memmove.c b/lib/libc/memmove.c
new file mode 100644
index 00000000..63acf267
--- /dev/null
+++ b/lib/libc/memmove.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <string.h>
+
+void *memmove(void *dst, const void *src, size_t len)
+{
+ /*
+ * The following test makes use of unsigned arithmetic overflow to
+ * more efficiently test the condition !(src <= dst && dst < str+len).
+ * It also avoids the situation where the more explicit test would give
+ * incorrect results were the calculation str+len to overflow (though
+ * that issue is probably moot as such usage is probably undefined
+ * behaviour and a bug anyway.
+ */
+ if ((size_t)dst - (size_t)src >= len) {
+ /* destination not in source data, so can safely use memcpy */
+ return memcpy(dst, src, len);
+ } else {
+ /* copy backwards... */
+ const char *end = dst;
+ const char *s = (const char *)src + len;
+ char *d = (char *)dst + len;
+ while (d != end)
+ *--d = *--s;
+ }
+ return dst;
+}
diff --git a/lib/libc/memset.c b/lib/libc/memset.c
new file mode 100644
index 00000000..03aa8096
--- /dev/null
+++ b/lib/libc/memset.c
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stddef.h>
+
+void *memset(void *dst, int val, size_t count)
+{
+ char *ptr = dst;
+
+ while (count--)
+ *ptr++ = val;
+
+ return dst;
+}
diff --git a/lib/libc/printf.c b/lib/libc/printf.c
new file mode 100644
index 00000000..2715a72d
--- /dev/null
+++ b/lib/libc/printf.c
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+#include <common/debug.h>
+
+#define get_num_va_args(_args, _lcount) \
+ (((_lcount) > 1) ? va_arg(_args, long long int) : \
+ (((_lcount) == 1) ? va_arg(_args, long int) : \
+ va_arg(_args, int)))
+
+#define get_unum_va_args(_args, _lcount) \
+ (((_lcount) > 1) ? va_arg(_args, unsigned long long int) : \
+ (((_lcount) == 1) ? va_arg(_args, unsigned long int) : \
+ va_arg(_args, unsigned int)))
+
+static int string_print(const char *str)
+{
+ int count = 0;
+
+ assert(str != NULL);
+
+ for ( ; *str != '\0'; str++) {
+ (void)putchar(*str);
+ count++;
+ }
+
+ return count;
+}
+
+static int unsigned_num_print(unsigned long long int unum, unsigned int radix,
+ char padc, int padn)
+{
+ /* Just need enough space to store 64 bit decimal integer */
+ char num_buf[20];
+ int i = 0, count = 0;
+ unsigned int rem;
+
+ do {
+ rem = unum % radix;
+ if (rem < 0xa)
+ num_buf[i] = '0' + rem;
+ else
+ num_buf[i] = 'a' + (rem - 0xa);
+ i++;
+ unum /= radix;
+ } while (unum > 0U);
+
+ if (padn > 0) {
+ while (i < padn) {
+ (void)putchar(padc);
+ count++;
+ padn--;
+ }
+ }
+
+ while (--i >= 0) {
+ (void)putchar(num_buf[i]);
+ count++;
+ }
+
+ return count;
+}
+
+/*******************************************************************
+ * Reduced format print for Trusted firmware.
+ * The following type specifiers are supported by this print
+ * %x - hexadecimal format
+ * %s - string format
+ * %d or %i - signed decimal format
+ * %u - unsigned decimal format
+ * %p - pointer format
+ *
+ * The following length specifiers are supported by this print
+ * %l - long int (64-bit on AArch64)
+ * %ll - long long int (64-bit on AArch64)
+ * %z - size_t sized integer formats (64 bit on AArch64)
+ *
+ * The following padding specifiers are supported by this print
+ * %0NN - Left-pad the number with 0s (NN is a decimal number)
+ *
+ * The print exits on all other formats specifiers other than valid
+ * combinations of the above specifiers.
+ *******************************************************************/
+int vprintf(const char *fmt, va_list args)
+{
+ int l_count;
+ long long int num;
+ unsigned long long int unum;
+ char *str;
+ char padc = '\0'; /* Padding character */
+ int padn; /* Number of characters to pad */
+ int count = 0; /* Number of printed characters */
+
+ while (*fmt != '\0') {
+ l_count = 0;
+ padn = 0;
+
+ if (*fmt == '%') {
+ fmt++;
+ /* Check the format specifier */
+loop:
+ switch (*fmt) {
+ case 'i': /* Fall through to next one */
+ case 'd':
+ num = get_num_va_args(args, l_count);
+ if (num < 0) {
+ (void)putchar('-');
+ unum = (unsigned long long int)-num;
+ padn--;
+ } else
+ unum = (unsigned long long int)num;
+
+ count += unsigned_num_print(unum, 10,
+ padc, padn);
+ break;
+ case 's':
+ str = va_arg(args, char *);
+ count += string_print(str);
+ break;
+ case 'p':
+ unum = (uintptr_t)va_arg(args, void *);
+ if (unum > 0U) {
+ count += string_print("0x");
+ padn -= 2;
+ }
+
+ count += unsigned_num_print(unum, 16,
+ padc, padn);
+ break;
+ case 'x':
+ unum = get_unum_va_args(args, l_count);
+ count += unsigned_num_print(unum, 16,
+ padc, padn);
+ break;
+ case 'z':
+ if (sizeof(size_t) == 8U)
+ l_count = 2;
+
+ fmt++;
+ goto loop;
+ case 'l':
+ l_count++;
+ fmt++;
+ goto loop;
+ case 'u':
+ unum = get_unum_va_args(args, l_count);
+ count += unsigned_num_print(unum, 10,
+ padc, padn);
+ break;
+ case '0':
+ padc = '0';
+ padn = 0;
+ fmt++;
+
+ for (;;) {
+ char ch = *fmt;
+ if ((ch < '0') || (ch > '9')) {
+ goto loop;
+ }
+ padn = (padn * 10) + (ch - '0');
+ fmt++;
+ }
+ assert(0); /* Unreachable */
+ default:
+ /* Exit on any other format specifier */
+ return -1;
+ }
+ fmt++;
+ continue;
+ }
+ (void)putchar(*fmt);
+ fmt++;
+ count++;
+ }
+
+ return count;
+}
+
+int printf(const char *fmt, ...)
+{
+ int count;
+ va_list va;
+
+ va_start(va, fmt);
+ count = vprintf(fmt, va);
+ va_end(va);
+
+ return count;
+}
diff --git a/lib/libc/putchar.c b/lib/libc/putchar.c
new file mode 100644
index 00000000..037e28ac
--- /dev/null
+++ b/lib/libc/putchar.c
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdio.h>
+
+#include <drivers/console.h>
+
+int putchar(int c)
+{
+ int res;
+ if (console_putc((unsigned char)c) >= 0)
+ res = c;
+ else
+ res = EOF;
+
+ return res;
+}
diff --git a/lib/libc/puts.c b/lib/libc/puts.c
new file mode 100644
index 00000000..2a0ca11c
--- /dev/null
+++ b/lib/libc/puts.c
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdio.h>
+
+int puts(const char *s)
+{
+ int count = 0;
+
+ while (*s != '\0') {
+ if (putchar(*s) == EOF)
+ return EOF;
+ s++;
+ count++;
+ }
+
+ if (putchar('\n') == EOF)
+ return EOF;
+
+ return count + 1;
+}
diff --git a/lib/libc/snprintf.c b/lib/libc/snprintf.c
new file mode 100644
index 00000000..38ad1c71
--- /dev/null
+++ b/lib/libc/snprintf.c
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdarg.h>
+
+#include <common/debug.h>
+#include <plat/common/platform.h>
+
+static void string_print(char **s, size_t n, size_t *chars_printed,
+ const char *str)
+{
+ while (*str != '\0') {
+ if (*chars_printed < n) {
+ *(*s) = *str;
+ (*s)++;
+ }
+
+ (*chars_printed)++;
+ str++;
+ }
+}
+
+static void unsigned_dec_print(char **s, size_t n, size_t *chars_printed,
+ unsigned int unum)
+{
+ /* Enough for a 32-bit unsigned decimal integer (4294967295). */
+ char num_buf[10];
+ int i = 0;
+ unsigned int rem;
+
+ do {
+ rem = unum % 10U;
+ num_buf[i++] = '0' + rem;
+ unum /= 10U;
+ } while (unum > 0U);
+
+ while (--i >= 0) {
+ if (*chars_printed < n) {
+ *(*s) = num_buf[i];
+ (*s)++;
+ }
+
+ (*chars_printed)++;
+ }
+}
+
+/*******************************************************************
+ * Reduced snprintf to be used for Trusted firmware.
+ * The following type specifiers are supported:
+ *
+ * %d or %i - signed decimal format
+ * %s - string format
+ * %u - unsigned decimal format
+ *
+ * The function panics on all other formats specifiers.
+ *
+ * It returns the number of characters that would be written if the
+ * buffer was big enough. If it returns a value lower than n, the
+ * whole string has been written.
+ *******************************************************************/
+int snprintf(char *s, size_t n, const char *fmt, ...)
+{
+ va_list args;
+ int num;
+ unsigned int unum;
+ char *str;
+ size_t chars_printed = 0U;
+
+ if (n == 0U) {
+ /* There isn't space for anything. */
+ } else if (n == 1U) {
+ /* Buffer is too small to actually write anything else. */
+ *s = '\0';
+ n = 0U;
+ } else {
+ /* Reserve space for the terminator character. */
+ n--;
+ }
+
+ va_start(args, fmt);
+ while (*fmt != '\0') {
+
+ if (*fmt == '%') {
+ fmt++;
+ /* Check the format specifier. */
+ switch (*fmt) {
+ case 'i':
+ case 'd':
+ num = va_arg(args, int);
+
+ if (num < 0) {
+ if (chars_printed < n) {
+ *s = '-';
+ s++;
+ }
+ chars_printed++;
+
+ unum = (unsigned int)-num;
+ } else {
+ unum = (unsigned int)num;
+ }
+
+ unsigned_dec_print(&s, n, &chars_printed, unum);
+ break;
+ case 's':
+ str = va_arg(args, char *);
+ string_print(&s, n, &chars_printed, str);
+ break;
+ case 'u':
+ unum = va_arg(args, unsigned int);
+ unsigned_dec_print(&s, n, &chars_printed, unum);
+ break;
+ default:
+ /* Panic on any other format specifier. */
+ ERROR("snprintf: specifier with ASCII code '%d' not supported.",
+ *fmt);
+ plat_panic_handler();
+ assert(0); /* Unreachable */
+ }
+ fmt++;
+ continue;
+ }
+
+ if (chars_printed < n) {
+ *s = *fmt;
+ s++;
+ }
+
+ fmt++;
+ chars_printed++;
+ }
+
+ va_end(args);
+
+ if (n > 0U)
+ *s = '\0';
+
+ return (int)chars_printed;
+}
diff --git a/lib/libc/strchr.c b/lib/libc/strchr.c
new file mode 100644
index 00000000..d94bb9e0
--- /dev/null
+++ b/lib/libc/strchr.c
@@ -0,0 +1,53 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Portions copyright (c) 2018, ARM Limited and Contributors.
+ * All rights reserved.
+ */
+
+#include <stddef.h>
+#include <string.h>
+
+char *
+strchr(const char *p, int ch)
+{
+ char c;
+
+ c = ch;
+ for (;; ++p) {
+ if (*p == c)
+ return ((char *)p);
+ if (*p == '\0')
+ return (NULL);
+ }
+ /* NOTREACHED */
+}
diff --git a/lib/libc/strcmp.c b/lib/libc/strcmp.c
new file mode 100644
index 00000000..b742f9b9
--- /dev/null
+++ b/lib/libc/strcmp.c
@@ -0,0 +1,52 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Portions copyright (c) 2018, ARM Limited and Contributors.
+ * All rights reserved.
+ */
+
+#include <string.h>
+
+/*
+ * Compare strings.
+ */
+int
+strcmp(const char *s1, const char *s2)
+{
+ while (*s1 == *s2++)
+ if (*s1++ == '\0')
+ return (0);
+ return (*(const unsigned char *)s1 - *(const unsigned char *)(s2 - 1));
+}
diff --git a/lib/libc/strlcpy.c b/lib/libc/strlcpy.c
new file mode 100644
index 00000000..c4f39bb9
--- /dev/null
+++ b/lib/libc/strlcpy.c
@@ -0,0 +1,52 @@
+/* $OpenBSD: strlcpy.c,v 1.12 2015/01/15 03:54:12 millert Exp $ */
+
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1998, 2015 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <stdint.h>
+#include <string.h>
+
+/*
+ * Copy string src to buffer dst of size dsize. At most dsize-1
+ * chars will be copied. Always NUL terminates (unless dsize == 0).
+ * Returns strlen(src); if retval >= dsize, truncation occurred.
+ */
+size_t
+strlcpy(char * dst, const char * src, size_t dsize)
+{
+ const char *osrc = src;
+ size_t nleft = dsize;
+
+ /* Copy as many bytes as will fit. */
+ if (nleft != 0) {
+ while (--nleft != 0) {
+ if ((*dst++ = *src++) == '\0')
+ break;
+ }
+ }
+
+ /* Not enough room in dst, add NUL and traverse rest of src. */
+ if (nleft == 0) {
+ if (dsize != 0)
+ *dst = '\0'; /* NUL-terminate dst */
+ while (*src++)
+ ;
+ }
+
+ return(src - osrc - 1); /* count does not include NUL */
+}
diff --git a/lib/libc/strlen.c b/lib/libc/strlen.c
new file mode 100644
index 00000000..3c276300
--- /dev/null
+++ b/lib/libc/strlen.c
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <string.h>
+
+size_t strlen(const char *s)
+{
+ const char *cursor = s;
+
+ while (*cursor)
+ cursor++;
+
+ return cursor - s;
+}
diff --git a/lib/libc/strncmp.c b/lib/libc/strncmp.c
new file mode 100644
index 00000000..ce9e5ed4
--- /dev/null
+++ b/lib/libc/strncmp.c
@@ -0,0 +1,53 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Portions copyright (c) 2018, ARM Limited and Contributors.
+ * All rights reserved.
+ */
+
+#include <string.h>
+
+int
+strncmp(const char *s1, const char *s2, size_t n)
+{
+
+ if (n == 0)
+ return (0);
+ do {
+ if (*s1 != *s2++)
+ return (*(const unsigned char *)s1 -
+ *(const unsigned char *)(s2 - 1));
+ if (*s1++ == '\0')
+ break;
+ } while (--n != 0);
+ return (0);
+}
diff --git a/lib/libc/strnlen.c b/lib/libc/strnlen.c
new file mode 100644
index 00000000..b944e95b
--- /dev/null
+++ b/lib/libc/strnlen.c
@@ -0,0 +1,46 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2009 David Schultz <das@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Portions copyright (c) 2018, ARM Limited and Contributors.
+ * All rights reserved.
+ */
+
+#include <string.h>
+
+size_t
+strnlen(const char *s, size_t maxlen)
+{
+ size_t len;
+
+ for (len = 0; len < maxlen; len++, s++) {
+ if (!*s)
+ break;
+ }
+ return (len);
+}
diff --git a/lib/libc/strrchr.c b/lib/libc/strrchr.c
new file mode 100644
index 00000000..cd435ff3
--- /dev/null
+++ b/lib/libc/strrchr.c
@@ -0,0 +1,49 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stddef.h>
+#include <string.h>
+
+char *
+strrchr(const char *p, int ch)
+{
+ char *save;
+ char c;
+
+ c = ch;
+ for (save = NULL;; ++p) {
+ if (*p == c)
+ save = (char *)p;
+ if (*p == '\0')
+ return (save);
+ }
+ /* NOTREACHED */
+}