summaryrefslogtreecommitdiff
path: root/builtin
diff options
context:
space:
mode:
Diffstat (limited to 'builtin')
-rw-r--r--builtin/assert.h10
-rw-r--r--builtin/build.mk6
-rw-r--r--builtin/ctype.h16
-rw-r--r--builtin/endian.h8
-rw-r--r--builtin/inttypes.h2
-rw-r--r--builtin/limits.h2
-rw-r--r--builtin/math.h2
-rw-r--r--builtin/stdarg.h10
-rw-r--r--builtin/stdbool.h8
-rw-r--r--builtin/stddef.h10
-rw-r--r--builtin/stdint.h68
-rw-r--r--builtin/stdio.h61
-rw-r--r--builtin/stdlib.c465
-rw-r--r--builtin/stdlib.h11
-rw-r--r--builtin/stdnoreturn.h5
-rw-r--r--builtin/string.h26
-rw-r--r--builtin/strings.h14
-rw-r--r--builtin/sys/types.h9
-rw-r--r--builtin/time.h2
19 files changed, 666 insertions, 69 deletions
diff --git a/builtin/assert.h b/builtin/assert.h
index 010198fd1b..b667a0d2a2 100644
--- a/builtin/assert.h
+++ b/builtin/assert.h
@@ -1,4 +1,4 @@
-/* Copyright 2016 The Chromium OS Authors. All rights reserved.
+/* Copyright 2016 The ChromiumOS Authors
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
@@ -11,6 +11,8 @@
/* Include CONFIG definitions for EC sources. */
#ifndef THIRD_PARTY
#include "common.h"
+#else
+#define test_mockable_noreturn noreturn
#endif
#ifdef __cplusplus
@@ -21,7 +23,7 @@ extern "C" {
#ifdef CONFIG_DEBUG_ASSERT_REBOOTS
#ifdef CONFIG_DEBUG_ASSERT_BRIEF
-noreturn void panic_assert_fail(const char *fname, int linenum);
+test_mockable_noreturn void panic_assert_fail(const char *fname, int linenum);
#define ASSERT(cond) \
do { \
if (!(cond)) \
@@ -30,8 +32,8 @@ noreturn void panic_assert_fail(const char *fname, int linenum);
#else /* !CONFIG_DEBUG_ASSERT_BRIEF */
-noreturn void panic_assert_fail(const char *msg, const char *func,
- const char *fname, int linenum);
+test_mockable_noreturn void panic_assert_fail(const char *msg, const char *func,
+ const char *fname, int linenum);
#define ASSERT(cond) \
do { \
if (!(cond)) \
diff --git a/builtin/build.mk b/builtin/build.mk
new file mode 100644
index 0000000000..6613bfec05
--- /dev/null
+++ b/builtin/build.mk
@@ -0,0 +1,6 @@
+# Copyright 2022 The ChromiumOS Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Build for EC's standard library implementation.
+builtin-y=stdlib.o
diff --git a/builtin/ctype.h b/builtin/ctype.h
new file mode 100644
index 0000000000..8844adca67
--- /dev/null
+++ b/builtin/ctype.h
@@ -0,0 +1,16 @@
+/* Copyright 2022 The ChromiumOS Authors
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef __CROS_EC_CTYPE_H__
+#define __CROS_EC_CTYPE_H__
+
+int isdigit(int c);
+int isspace(int c);
+int isalpha(int c);
+int isupper(int c);
+int isprint(int c);
+int tolower(int c);
+
+#endif /* __CROS_EC_CTYPE_H__ */
diff --git a/builtin/endian.h b/builtin/endian.h
index 65c064bb78..0220836dca 100644
--- a/builtin/endian.h
+++ b/builtin/endian.h
@@ -1,4 +1,4 @@
-/* Copyright 2016 The Chromium OS Authors. All rights reserved.
+/* Copyright 2016 The ChromiumOS Authors
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
@@ -17,7 +17,7 @@ extern "C" {
* host byte order. Note that the code currently does not require functions
* for converting little endian integers.
*/
-#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
+#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
static inline uint16_t be16toh(uint16_t in)
{
@@ -40,10 +40,10 @@ static inline uint64_t be64toh(uint64_t in)
#define htole32(x) (uint32_t)(x)
#define htole64(x) (uint64_t)(x)
-#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
+#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
#ifdef __cplusplus
}
#endif
-#endif /* __EC_BUILTIN_ENDIAN_H */
+#endif /* __EC_BUILTIN_ENDIAN_H */
diff --git a/builtin/inttypes.h b/builtin/inttypes.h
index c442fbe499..1ef305548b 100644
--- a/builtin/inttypes.h
+++ b/builtin/inttypes.h
@@ -1,4 +1,4 @@
-/* Copyright 2019 The Chromium OS Authors. All rights reserved.
+/* Copyright 2019 The ChromiumOS Authors
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
diff --git a/builtin/limits.h b/builtin/limits.h
index e5deb70291..0e185614ae 100644
--- a/builtin/limits.h
+++ b/builtin/limits.h
@@ -1,4 +1,4 @@
-/* Copyright 2020 The Chromium OS Authors. All rights reserved.
+/* Copyright 2020 The ChromiumOS Authors
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
diff --git a/builtin/math.h b/builtin/math.h
index 9292ac8b34..c015d9d18d 100644
--- a/builtin/math.h
+++ b/builtin/math.h
@@ -1,4 +1,4 @@
-/* Copyright 2021 The Chromium OS Authors. All rights reserved.
+/* Copyright 2021 The ChromiumOS Authors
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
diff --git a/builtin/stdarg.h b/builtin/stdarg.h
index 66ab940b16..5bf0aa8aa2 100644
--- a/builtin/stdarg.h
+++ b/builtin/stdarg.h
@@ -1,4 +1,4 @@
-/* Copyright 2016 The Chromium OS Authors. All rights reserved.
+/* Copyright 2016 The ChromiumOS Authors
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
@@ -13,10 +13,10 @@
*/
#ifdef __GNUC__
-#define va_start(v, l) __builtin_va_start(v, l)
-#define va_end(v) __builtin_va_end(v)
-#define va_arg(v, l) __builtin_va_arg(v, l)
-typedef __builtin_va_list va_list;
+#define va_start(v, l) __builtin_va_start(v, l)
+#define va_end(v) __builtin_va_end(v)
+#define va_arg(v, l) __builtin_va_arg(v, l)
+typedef __builtin_va_list va_list;
#else
#include_next <stdarg.h>
#endif
diff --git a/builtin/stdbool.h b/builtin/stdbool.h
index 6e0f92dfc0..72d4927484 100644
--- a/builtin/stdbool.h
+++ b/builtin/stdbool.h
@@ -1,4 +1,4 @@
-/* Copyright 2016 The Chromium OS Authors. All rights reserved.
+/* Copyright 2016 The ChromiumOS Authors
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
@@ -6,8 +6,8 @@
#ifndef __CROS_EC_STDBOOL_H__
#define __CROS_EC_STDBOOL_H__
-#define bool _Bool
-#define true 1
-#define false 0
+#define bool _Bool
+#define true 1
+#define false 0
#endif /* __CROS_EC_STDBOOL_H__ */
diff --git a/builtin/stddef.h b/builtin/stddef.h
index 69fb1982c7..9e69ba55ad 100644
--- a/builtin/stddef.h
+++ b/builtin/stddef.h
@@ -1,4 +1,4 @@
-/* Copyright 2016 The Chromium OS Authors. All rights reserved.
+/* Copyright 2016 The ChromiumOS Authors
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
@@ -11,12 +11,6 @@
#endif
typedef __SIZE_TYPE__ size_t;
-/* There is a GCC macro for a size_t type, but not for a ssize_t type.
- * The following construct convinces GCC to make __SIZE_TYPE__ signed.
- */
-#define unsigned signed
-typedef __SIZE_TYPE__ ssize_t;
-#undef unsigned
#ifndef NULL
#define NULL ((void *)0)
@@ -36,7 +30,7 @@ typedef __WCHAR_TYPE__ wchar_t;
* check for safety.
*/
#ifndef offsetof
-#define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER)
+#define offsetof(TYPE, MEMBER) __builtin_offsetof(TYPE, MEMBER)
#endif
#endif /* __CROS_EC_STDDEF_H__ */
diff --git a/builtin/stdint.h b/builtin/stdint.h
index dedc9de475..5a107e1730 100644
--- a/builtin/stdint.h
+++ b/builtin/stdint.h
@@ -1,4 +1,4 @@
-/* Copyright 2016 The Chromium OS Authors. All rights reserved.
+/* Copyright 2016 The ChromiumOS Authors
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
@@ -6,43 +6,43 @@
#ifndef __CROS_EC_STDINT_H__
#define __CROS_EC_STDINT_H__
-typedef unsigned char uint8_t;
-typedef signed char int8_t;
+typedef unsigned char uint8_t;
+typedef signed char int8_t;
-typedef unsigned short uint16_t;
-typedef signed short int16_t;
+typedef unsigned short uint16_t;
+typedef signed short int16_t;
-typedef unsigned int uint32_t;
-typedef signed int int32_t;
+typedef unsigned int uint32_t;
+typedef signed int int32_t;
typedef unsigned long long uint64_t;
-typedef signed long long int64_t;
+typedef signed long long int64_t;
-typedef unsigned int uintptr_t;
-typedef int intptr_t;
+typedef unsigned int uintptr_t;
+typedef int intptr_t;
/* uint_leastX_t represents the smallest type available with at least X bits.
* uint_fastX_t represents the fastest type available with at least X bits.
*/
-typedef uint8_t uint_least8_t;
-typedef uint16_t uint_least16_t;
-typedef uint32_t uint_least32_t;
-typedef uint64_t uint_least64_t;
-
-typedef int8_t int_least8_t;
-typedef int16_t int_least16_t;
-typedef int32_t int_least32_t;
-typedef int64_t int_least64_t;
-
-typedef uint8_t uint_fast8_t;
-typedef uint16_t uint_fast16_t;
-typedef uint32_t uint_fast32_t;
-typedef uint64_t uint_fast64_t;
-
-typedef int8_t int_fast8_t;
-typedef int16_t int_fast16_t;
-typedef int32_t int_fast32_t;
-typedef int64_t int_fast64_t;
+typedef uint8_t uint_least8_t;
+typedef uint16_t uint_least16_t;
+typedef uint32_t uint_least32_t;
+typedef uint64_t uint_least64_t;
+
+typedef int8_t int_least8_t;
+typedef int16_t int_least16_t;
+typedef int32_t int_least32_t;
+typedef int64_t int_least64_t;
+
+typedef uint8_t uint_fast8_t;
+typedef uint16_t uint_fast16_t;
+typedef uint32_t uint_fast32_t;
+typedef uint64_t uint_fast64_t;
+
+typedef int8_t int_fast8_t;
+typedef int16_t int_fast16_t;
+typedef int32_t int_fast32_t;
+typedef int64_t int_fast64_t;
#ifndef UINT8_MAX
#define UINT8_MAX (255U)
@@ -67,12 +67,15 @@ typedef int64_t int_fast64_t;
#ifndef INT32_MAX
#define INT32_MAX (2147483647U)
#endif
+#ifndef INT32_MIN
+#define INT32_MIN (-2147483648)
+#endif
#ifndef UINT64_C
-#define UINT64_C(c) c ## ULL
+#define UINT64_C(c) c##ULL
#endif
#ifndef INT64_C
-#define INT64_C(c) c ## LL
+#define INT64_C(c) c##LL
#endif
#ifndef UINT64_MAX
@@ -81,5 +84,8 @@ typedef int64_t int_fast64_t;
#ifndef INT64_MAX
#define INT64_MAX INT64_C(9223372036854775807)
#endif
+#ifndef INT64_MIN
+#define INT64_MIN (INT64_C(-9223372036854775807) - 1)
+#endif
#endif /* __CROS_EC_STDINT_H__ */
diff --git a/builtin/stdio.h b/builtin/stdio.h
new file mode 100644
index 0000000000..7536499feb
--- /dev/null
+++ b/builtin/stdio.h
@@ -0,0 +1,61 @@
+/* Copyright 2022 The ChromiumOS Authors
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef __CROS_EC_STDIO_H__
+#define __CROS_EC_STDIO_H__
+
+#include <stddef.h>
+#include <stdarg.h>
+
+#include "common.h"
+
+/**
+ * Print formatted outut to a string.
+ *
+ * Guarantees null-termination if size!=0.
+ *
+ * @param str Destination string
+ * @param size Size of destination in bytes
+ * @param format Format string
+ * @return EC_SUCCESS, or EC_ERROR_OVERFLOW if the output was truncated.
+ */
+__attribute__((__format__(__printf__, 3, 4)))
+__warn_unused_result __stdlib_compat int
+crec_snprintf(char *str, size_t size, const char *format, ...);
+
+/**
+ * Print formatted output to a string.
+ *
+ * Guarantees null-termination if size!=0.
+ *
+ * @param str Destination string
+ * @param size Size of destination in bytes
+ * @param format Format string
+ * @param args Parameters
+ * @return The string length written to str, or a negative value on error.
+ * The negative values can be -EC_ERROR_INVAL or -EC_ERROR_OVERFLOW.
+ */
+__warn_unused_result __stdlib_compat int
+crec_vsnprintf(char *str, size_t size, const char *format, va_list args);
+
+/*
+ * Create weak aliases to the crec_* printf functions. This lets us call the
+ * crec_* printf functions in tests that link the C standard library.
+ */
+
+/**
+ * Alias to crec_snprintf.
+ */
+__attribute__((__format__(__printf__, 3, 4)))
+__warn_unused_result __stdlib_compat int
+snprintf(char *str, size_t size, const char *format, ...);
+
+/**
+ * Alias to crec_vsnprintf.
+ */
+__warn_unused_result __stdlib_compat int
+vsnprintf(char *str, size_t size, const char *format, va_list args);
+
+#endif /* __CROS_EC_STDIO_H__ */
diff --git a/builtin/stdlib.c b/builtin/stdlib.c
new file mode 100644
index 0000000000..0d654f0395
--- /dev/null
+++ b/builtin/stdlib.c
@@ -0,0 +1,465 @@
+/* Copyright 2021 The ChromiumOS Authors
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/* Standard library utility functions for Chrome EC */
+
+#include "common.h"
+#include "console.h"
+#include "printf.h"
+#include "util.h"
+
+#include <stdio.h>
+
+/*
+ * The following macros are defined in stdlib.h in the C standard library, which
+ * conflict with the definitions in this file.
+ */
+#undef isspace
+#undef isdigit
+#undef isalpha
+#undef isupper
+#undef isprint
+#undef tolower
+
+/* Context for snprintf() */
+struct snprintf_context {
+ char *str;
+ int size;
+};
+
+/**
+ * Add a character to the string context.
+ *
+ * @param context Context receiving character
+ * @param c Character to add
+ * @return 0 if character added, 1 if character dropped because no space.
+ */
+static int snprintf_addchar(void *context, int c)
+{
+ struct snprintf_context *ctx = (struct snprintf_context *)context;
+
+ if (!ctx->size)
+ return 1;
+
+ *(ctx->str++) = c;
+ ctx->size--;
+ return 0;
+}
+
+int crec_vsnprintf(char *str, size_t size, const char *format, va_list args)
+{
+ struct snprintf_context ctx;
+ int rv;
+
+ if (!str || !format || size <= 0)
+ return -EC_ERROR_INVAL;
+
+ ctx.str = str;
+ ctx.size = size - 1; /* Reserve space for terminating '\0' */
+
+ rv = vfnprintf(snprintf_addchar, &ctx, format, args);
+
+ /* Terminate string */
+ *ctx.str = '\0';
+
+ return (rv == EC_SUCCESS) ? (ctx.str - str) : -rv;
+}
+#ifndef CONFIG_ZEPHYR
+int vsnprintf(char *str, size_t size, const char *format, va_list args)
+ __attribute__((weak, alias("crec_vsnprintf")));
+#endif /* CONFIG_ZEPHYR */
+
+int crec_snprintf(char *str, size_t size, const char *format, ...)
+{
+ va_list args;
+ int rv;
+
+ va_start(args, format);
+ rv = crec_vsnprintf(str, size, format, args);
+ va_end(args);
+
+ return rv;
+}
+#ifndef CONFIG_ZEPHYR
+int snprintf(char *str, size_t size, const char *format, ...)
+ __attribute__((weak, alias("crec_snprintf")));
+#endif /* CONFIG_ZEPHYR */
+
+/*
+ * TODO(b/237712836): Zephyr's libc should provide strcasecmp. For now we'll
+ * use the EC implementation.
+ */
+__stdlib_compat int strcasecmp(const char *s1, const char *s2)
+{
+ int diff;
+
+ do {
+ diff = tolower(*s1) - tolower(*s2);
+ if (diff)
+ return diff;
+ } while (*(s1++) && *(s2++));
+ return 0;
+}
+
+/*
+ * TODO(b/237712836): Remove this conditional once strcasecmp is added to
+ * Zephyr's libc.
+ */
+#ifndef CONFIG_ZEPHYR
+__stdlib_compat size_t strlen(const char *s)
+{
+ int len = 0;
+
+ while (*s++)
+ len++;
+
+ return len;
+}
+
+__stdlib_compat size_t strnlen(const char *s, size_t maxlen)
+{
+ size_t len = 0;
+
+ while (len < maxlen && *s) {
+ s++;
+ len++;
+ }
+ return len;
+}
+
+__stdlib_compat size_t strcspn(const char *s, const char *reject)
+{
+ size_t i;
+ size_t reject_len = strlen(reject);
+
+ for (i = 0; s[i] != 0; i++)
+ for (size_t j = 0; j < reject_len; j++)
+ if (s[i] == reject[j])
+ return i;
+ return i;
+}
+
+__stdlib_compat int isspace(int c)
+{
+ return c == ' ' || c == '\t' || c == '\r' || c == '\n';
+}
+
+__stdlib_compat int isdigit(int c)
+{
+ return c >= '0' && c <= '9';
+}
+
+__stdlib_compat int isalpha(int c)
+{
+ return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
+}
+
+__stdlib_compat int isupper(int c)
+{
+ return c >= 'A' && c <= 'Z';
+}
+
+__stdlib_compat int isprint(int c)
+{
+ return c >= ' ' && c <= '~';
+}
+
+__stdlib_compat int tolower(int c)
+{
+ return c >= 'A' && c <= 'Z' ? c + 'a' - 'A' : c;
+}
+
+__stdlib_compat int strncasecmp(const char *s1, const char *s2, size_t size)
+{
+ int diff;
+
+ if (!size)
+ return 0;
+
+ do {
+ diff = tolower(*s1) - tolower(*s2);
+ if (diff)
+ return diff;
+ } while (*(s1++) && *(s2++) && --size);
+ return 0;
+}
+
+__stdlib_compat char *strstr(const char *s1, const char *s2)
+{
+ const char *p, *q, *r;
+ size_t len1 = strlen(s1);
+ size_t len2 = strlen(s2);
+
+ if (len1 == 0 || len2 == 0 || len1 < len2)
+ return NULL;
+
+ r = s1 + len1 - len2 + 1;
+ for (; s1 < r; s1++) {
+ if (*s1 == *s2) {
+ p = s1 + 1;
+ q = s2 + 1;
+ for (; q < s2 + len2;) {
+ if (*p++ != *q++)
+ break;
+ }
+ if (*q == '\0')
+ return (char *)s1;
+ }
+ }
+ return NULL;
+}
+
+__stdlib_compat unsigned long long int strtoull(const char *nptr, char **endptr,
+ int base)
+{
+ uint64_t result = 0;
+ int c = '\0';
+
+ while ((c = *nptr++) && isspace(c))
+ ;
+
+ if (c == '+') {
+ c = *nptr++;
+ } else if (c == '-') {
+ if (endptr)
+ *endptr = (char *)nptr - 1;
+ return result;
+ }
+
+ base = find_base(base, &c, &nptr);
+
+ while (c) {
+ if (c >= '0' && c < '0' + MIN(base, 10))
+ result = result * base + (c - '0');
+ else if (c >= 'A' && c < 'A' + base - 10)
+ result = result * base + (c - 'A' + 10);
+ else if (c >= 'a' && c < 'a' + base - 10)
+ result = result * base + (c - 'a' + 10);
+ else
+ break;
+
+ c = *nptr++;
+ }
+
+ if (endptr)
+ *endptr = (char *)nptr - 1;
+ return result;
+}
+BUILD_ASSERT(sizeof(unsigned long long int) == sizeof(uint64_t));
+
+__stdlib_compat int atoi(const char *nptr)
+{
+ int result = 0;
+ int neg = 0;
+ char c = '\0';
+
+ while ((c = *nptr++) && isspace(c))
+ ;
+
+ if (c == '-') {
+ neg = 1;
+ c = *nptr++;
+ }
+
+ while (isdigit(c)) {
+ result = result * 10 + (c - '0');
+ c = *nptr++;
+ }
+
+ return neg ? -result : result;
+}
+
+__keep __stdlib_compat int memcmp(const void *s1, const void *s2, size_t len)
+{
+ const char *sa = s1;
+ const char *sb = s2;
+ int diff = 0;
+
+ while (len-- > 0) {
+ diff = *(sa++) - *(sb++);
+ if (diff)
+ return diff;
+ }
+
+ return 0;
+}
+
+#if !(__has_feature(address_sanitizer) || __has_feature(memory_sanitizer))
+__keep __stdlib_compat void *memcpy(void *dest, const void *src, size_t len)
+{
+ char *d = (char *)dest;
+ const char *s = (const char *)src;
+ uint32_t *dw;
+ const uint32_t *sw;
+ char *head;
+ char *const tail = (char *)dest + len;
+ /* Set 'body' to the last word boundary */
+ uint32_t *const body = (uint32_t *)((uintptr_t)tail & ~3);
+
+ if (((uintptr_t)dest & 3) != ((uintptr_t)src & 3)) {
+ /* Misaligned. no body, no tail. */
+ head = tail;
+ } else {
+ /* Aligned */
+ if ((uintptr_t)tail < (((uintptr_t)d + 3) & ~3))
+ /* len is shorter than the first word boundary */
+ head = tail;
+ else
+ /* Set 'head' to the first word boundary */
+ head = (char *)(((uintptr_t)d + 3) & ~3);
+ }
+
+ /* Copy head */
+ while (d < head)
+ *(d++) = *(s++);
+
+ /* Copy body */
+ dw = (uint32_t *)d;
+ sw = (uint32_t *)s;
+ while (dw < body)
+ *(dw++) = *(sw++);
+
+ /* Copy tail */
+ d = (char *)dw;
+ s = (const char *)sw;
+ while (d < tail)
+ *(d++) = *(s++);
+
+ return dest;
+}
+#endif /* address_sanitizer || memory_sanitizer */
+
+#if !(__has_feature(address_sanitizer) || __has_feature(memory_sanitizer))
+__keep __stdlib_compat __visible void *memset(void *dest, int c, size_t len)
+{
+ char *d = (char *)dest;
+ uint32_t cccc;
+ uint32_t *dw;
+ char *head;
+ char *const tail = (char *)dest + len;
+ /* Set 'body' to the last word boundary */
+ uint32_t *const body = (uint32_t *)((uintptr_t)tail & ~3);
+
+ c &= 0xff; /* Clear upper bits before ORing below */
+ cccc = c | (c << 8) | (c << 16) | (c << 24);
+
+ if ((uintptr_t)tail < (((uintptr_t)d + 3) & ~3))
+ /* len is shorter than the first word boundary */
+ head = tail;
+ else
+ /* Set 'head' to the first word boundary */
+ head = (char *)(((uintptr_t)d + 3) & ~3);
+
+ /* Copy head */
+ while (d < head)
+ *(d++) = c;
+
+ /* Copy body */
+ dw = (uint32_t *)d;
+ while (dw < body)
+ *(dw++) = cccc;
+
+ /* Copy tail */
+ d = (char *)dw;
+ while (d < tail)
+ *(d++) = c;
+
+ return dest;
+}
+#endif /* address_sanitizer || memory_sanitizer */
+
+#if !(__has_feature(address_sanitizer) || __has_feature(memory_sanitizer))
+__keep __stdlib_compat void *memmove(void *dest, const void *src, size_t len)
+{
+ if ((uintptr_t)dest <= (uintptr_t)src ||
+ (uintptr_t)dest >= (uintptr_t)src + len) {
+ /* Start of destination doesn't overlap source, so just use
+ * memcpy().
+ */
+ return memcpy(dest, src, len);
+ } else {
+ /* Need to copy from tail because there is overlap. */
+ char *d = (char *)dest + len;
+ const char *s = (const char *)src + len;
+ uint32_t *dw;
+ const uint32_t *sw;
+ char *head;
+ char *const tail = (char *)dest;
+ /* Set 'body' to the last word boundary */
+ uint32_t *const body = (uint32_t *)(((uintptr_t)tail + 3) & ~3);
+
+ if (((uintptr_t)dest & 3) != ((uintptr_t)src & 3)) {
+ /* Misaligned. no body, no tail. */
+ head = tail;
+ } else {
+ /* Aligned */
+ if ((uintptr_t)tail > ((uintptr_t)d & ~3))
+ /* Shorter than the first word boundary */
+ head = tail;
+ else
+ /* Set 'head' to the first word boundary */
+ head = (char *)((uintptr_t)d & ~3);
+ }
+
+ /* Copy head */
+ while (d > head)
+ *(--d) = *(--s);
+
+ /* Copy body */
+ dw = (uint32_t *)d;
+ sw = (uint32_t *)s;
+ while (dw > body)
+ *(--dw) = *(--sw);
+
+ /* Copy tail */
+ d = (char *)dw;
+ s = (const char *)sw;
+ while (d > tail)
+ *(--d) = *(--s);
+
+ return dest;
+ }
+}
+#endif /* address_sanitizer || memory_sanitizer */
+
+__stdlib_compat void *memchr(const void *buffer, int c, size_t n)
+{
+ char *current = (char *)buffer;
+ char *end = current + n;
+
+ while (current != end) {
+ if (*current == c)
+ return current;
+ current++;
+ }
+ return NULL;
+}
+
+__stdlib_compat char *strncpy(char *dest, const char *src, size_t n)
+{
+ char *d = dest;
+
+ while (n && *src) {
+ *d++ = *src++;
+ n--;
+ }
+ if (n)
+ *d = '\0';
+ return dest;
+}
+
+__stdlib_compat int strncmp(const char *s1, const char *s2, size_t n)
+{
+ while (n--) {
+ if (*s1 != *s2)
+ return *s1 - *s2;
+ if (!*s1)
+ break;
+ s1++;
+ s2++;
+ }
+ return 0;
+}
+#endif /* !CONFIG_ZEPHYR */
diff --git a/builtin/stdlib.h b/builtin/stdlib.h
new file mode 100644
index 0000000000..fcce72ee8d
--- /dev/null
+++ b/builtin/stdlib.h
@@ -0,0 +1,11 @@
+/* Copyright 2022 The ChromiumOS Authors
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef __CROS_EC_STDLIB_H__
+#define __CROS_EC_STDLIB_H__
+
+int atoi(const char *nptr);
+
+#endif /* __CROS_EC_STDLIB_H__ */
diff --git a/builtin/stdnoreturn.h b/builtin/stdnoreturn.h
index 659d3c540f..078a0d6698 100644
--- a/builtin/stdnoreturn.h
+++ b/builtin/stdnoreturn.h
@@ -1,4 +1,4 @@
-/* Copyright 2020 The Chromium OS Authors. All rights reserved.
+/* Copyright 2020 The ChromiumOS Authors
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
@@ -9,7 +9,8 @@
/*
* Only defined for C: https://en.cppreference.com/w/c/language/_Noreturn
*
- * C++ uses [[noreturn]]: https://en.cppreference.com/w/cpp/language/attributes/noreturn
+ * C++ uses [[noreturn]]:
+ * https://en.cppreference.com/w/cpp/language/attributes/noreturn
*/
#ifndef __cplusplus
#ifndef noreturn
diff --git a/builtin/string.h b/builtin/string.h
index 8c9a71bd75..742d75a478 100644
--- a/builtin/string.h
+++ b/builtin/string.h
@@ -1,12 +1,10 @@
-/* Copyright 2016 The Chromium OS Authors. All rights reserved.
+/* Copyright 2016 The ChromiumOS Authors
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
-/* This header is only needed for CR50 compatibility */
-
-#ifndef __CROS_EC_STRINGS_H__
-#define __CROS_EC_STRINGS_H__
+#ifndef __CROS_EC_STRING_H__
+#define __CROS_EC_STRING_H__
#include <stddef.h>
@@ -20,12 +18,28 @@ void *memmove(void *dest, const void *src, size_t n);
void *memset(void *dest, int c, size_t len);
void *memchr(const void *buffer, int c, size_t n);
+size_t strlen(const char *s);
size_t strnlen(const char *s, size_t maxlen);
char *strncpy(char *dest, const char *src, size_t n);
int strncmp(const char *s1, const char *s2, size_t n);
+/**
+ * Calculates the length of the initial segment of s which consists
+ * entirely of bytes not in reject.
+ */
+size_t strcspn(const char *s, const char *reject);
+
+/**
+ * Find the first occurrence of the substring <s2> in the string <s1>
+ *
+ * @param s1 String where <s2> is searched.
+ * @param s2 Substring to be located in <s1>
+ * @return Pointer to the located substring or NULL if not found.
+ */
+char *strstr(const char *s1, const char *s2);
+
#ifdef __cplusplus
}
#endif
-#endif /* __CROS_EC_STRINGS_H__ */
+#endif /* __CROS_EC_STRING_H__ */
diff --git a/builtin/strings.h b/builtin/strings.h
new file mode 100644
index 0000000000..cbcc858c36
--- /dev/null
+++ b/builtin/strings.h
@@ -0,0 +1,14 @@
+/* Copyright 2022 The ChromiumOS Authors
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef __CROS_EC_STRINGS_H__
+#define __CROS_EC_STRINGS_H__
+
+#include <stddef.h>
+
+int strcasecmp(const char *s1, const char *s2);
+int strncasecmp(const char *s1, const char *s2, size_t size);
+
+#endif /* __CROS_EC_STRINGS_H__ */
diff --git a/builtin/sys/types.h b/builtin/sys/types.h
index 3f8de955e0..01fc1a7749 100644
--- a/builtin/sys/types.h
+++ b/builtin/sys/types.h
@@ -1,4 +1,4 @@
-/* Copyright 2022 The ChromiumOS Authors.
+/* Copyright 2022 The ChromiumOS Authors
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
@@ -9,4 +9,11 @@
/* Data type for POSIX style clock() implementation */
typedef long clock_t;
+/* There is a GCC macro for a size_t type, but not for a ssize_t type.
+ * The following construct convinces GCC to make __SIZE_TYPE__ signed.
+ */
+#define unsigned signed
+typedef __SIZE_TYPE__ ssize_t;
+#undef unsigned
+
#endif /* __CROS_EC_SYS_TYPES_H__ */
diff --git a/builtin/time.h b/builtin/time.h
index a069ae18c9..36b07b4721 100644
--- a/builtin/time.h
+++ b/builtin/time.h
@@ -1,4 +1,4 @@
-/* Copyright 2016 The Chromium OS Authors. All rights reserved.
+/* Copyright 2016 The ChromiumOS Authors
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/