From 390db422d8bf98458233b67021cc1d9d2028be11 Mon Sep 17 00:00:00 2001 From: Yifan Liu Date: Mon, 3 Nov 2025 08:24:21 +0000 Subject: [PATCH] hv: lib: Add several missing standard string/memory APIs Integrating libfdt requires the presence of these APIs. Tracked-On: #8838 Signed-off-by: Yifan Liu Acked-by: Wang Yu1 --- hypervisor/include/lib/memory.h | 4 +- hypervisor/include/lib/rtl.h | 7 +- hypervisor/include/lib/types.h | 1 + hypervisor/lib/memory.c | 58 +++++++++++ hypervisor/lib/string.c | 170 +++++++++++++++++++++----------- 5 files changed, 183 insertions(+), 57 deletions(-) diff --git a/hypervisor/include/lib/memory.h b/hypervisor/include/lib/memory.h index 8ba1985e9..57789f87a 100644 --- a/hypervisor/include/lib/memory.h +++ b/hypervisor/include/lib/memory.h @@ -32,6 +32,8 @@ void memcpy_backwards(void *d, const void *s, size_t slen); #endif int32_t memcpy_s(void *d, size_t dmax, const void *s, size_t slen); - +int memcmp(const void *s1, const void *s2, size_t count); +void *memmove(void *d, const void *s, size_t slen); +void *memchr(const void *s, int c, size_t slen); #endif /* MEMORY_LIB_H */ diff --git a/hypervisor/include/lib/rtl.h b/hypervisor/include/lib/rtl.h index d56d5e53c..234d8dfbd 100644 --- a/hypervisor/include/lib/rtl.h +++ b/hypervisor/include/lib/rtl.h @@ -38,11 +38,16 @@ static inline bool is_eol(char c) int32_t strcmp(const char *s1_arg, const char *s2_arg); int32_t strncmp(const char *s1_arg, const char *s2_arg, size_t n_arg); int32_t strncpy_s(char *d, size_t dmax, const char *s, size_t slen); -char *strchr(char *s_arg, char ch); +char *strchr(const char *s_arg, char ch); size_t strnlen_s(const char *str_arg, size_t maxlen_arg); int64_t strtol_deci(const char *nptr); uint64_t strtoul_hex(const char *nptr); +uint64_t strtoul(const char * nptr, char **endptr, int base); char *strstr_s(const char *str1, size_t maxlen1, const char *str2, size_t maxlen2); int32_t strncat_s(char *dest, size_t dmax, const char *src, size_t slen); +size_t strlen(const char *str); +size_t strnlen(const char *str, size_t count); +char *strrchr(const char *s, char ch); +char *strcpy(char *d, const char *s); #endif /* RTL_H */ diff --git a/hypervisor/include/lib/types.h b/hypervisor/include/lib/types.h index 073753fcd..1edefe40d 100644 --- a/hypervisor/include/lib/types.h +++ b/hypervisor/include/lib/types.h @@ -24,6 +24,7 @@ typedef unsigned short uint16_t; typedef signed int int32_t; typedef unsigned int uint32_t; typedef unsigned long uint64_t; +typedef unsigned long uintptr_t; typedef signed long int64_t; typedef unsigned int size_t; typedef __builtin_va_list va_list; diff --git a/hypervisor/lib/memory.c b/hypervisor/lib/memory.c index 6d88cb27d..76eaba3f6 100644 --- a/hypervisor/lib/memory.c +++ b/hypervisor/lib/memory.c @@ -66,3 +66,61 @@ int32_t memcpy_s(void *d, size_t dmax, const void *s, size_t slen) return ret; } + +int memcmp(const void *s1, const void *s2, size_t count) +{ + const char *t1 = s1; + const char *t2 = s2; + int ret = 0; + + for (; count > 0 && (*t1 == *t2); count--) { + t1++; + t2++; + } + + if (count > 0) { + ret = *(unsigned char *)t1 - *(unsigned char *)t2; + } + + return ret; +} + +void *memmove(void *d, const void *s, size_t slen) +{ + char *t1 = (char *)d; + const char *t2 = (char *)s; + + if (d == s) { + /* do nothing */ + } else if (d < s) { + while (slen > 0) { + *t1++ = *t2++; + slen--; + } + } else { + t1 = (char *)d + slen - 1; + t2 = (char *)s + slen - 1; + + while (slen > 0) { + *t1-- = *t2--; + slen--; + } + } + + return d; +} + +void *memchr(const void *s, int c, size_t slen) +{ + void *ret = NULL; + const unsigned char *t; + + for (t = s; slen > 0; slen--) { + if ((unsigned char)c == *t++) { + ret = (void *)(t - 1); + break; + } + } + + return ret; +} diff --git a/hypervisor/lib/string.c b/hypervisor/lib/string.c index 339e9f465..6e23f8b06 100644 --- a/hypervisor/lib/string.c +++ b/hypervisor/lib/string.c @@ -6,19 +6,81 @@ #include #include -static inline char hex_digit_value(char ch) +uint64_t strtoul(const char * nptr, char **endptr, int base) { - char c; - if (('0' <= ch) && (ch <= '9')) { - c = ch - '0'; - } else if (('a' <= ch) && (ch <= 'f')) { - c = ch - 'a' + 10; - } else if (('A' <= ch) && (ch <= 'F')) { - c = ch - 'A' + 10; + const char *s; + unsigned long acc, cutoff; + int c; + int neg, any, cutlim; + + /* + * See strtol for comments as to the logic used. + */ + s = nptr; + do { + c = (unsigned char) *s++; + } while (is_space(c)); + + if (c == '-') { + neg = 1; + c = *s++; } else { - c = -1; + neg = 0; + if (c == '+') + c = *s++; } - return c; + + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X')) { + c = s[1]; + s += 2; + base = 16; + } + + if (base == 0) { + base = c == '0' ? 8 : 10; + } + + cutoff = ULONG_MAX / (unsigned long)base; + cutlim = ULONG_MAX % (unsigned long)base; + + for (acc = 0, any = 0;; c = (unsigned char) *s++) { + if (c >= '0' && c <= '9') { + c -= '0'; + } else if (c >= 'A' && c <= 'Z') { + c -= 'A' - 10; + } else if (c >= 'a' && c <= 'z') { + c -= 'a' - 10; + } else { + break; + } + if (c >= base) { + break; + } + + if (any < 0) { + continue; + } + + if (acc > cutoff || (acc == cutoff && c > cutlim)) { + any = -1; + acc = ULONG_MAX; + } else { + any = 1; + acc *= (unsigned long)base; + acc += c; + } + } + + if (neg && any > 0) { + acc = -acc; + } + + if (endptr != 0) { + *endptr = (char *) (any ? s - 1 : nptr); + } + + return (acc); } /* @@ -26,58 +88,56 @@ static inline char hex_digit_value(char ch) */ uint64_t strtoul_hex(const char *nptr) { - const char *s = nptr; - char c, digit; - uint64_t acc, cutoff, cutlim; - uint64_t base = 16UL; - int32_t any; - - /* - * See strtol for comments as to the logic used. - */ - do { - c = *s; - s++; - } while (is_space(c)); - - if ((c == '0') && ((*s == 'x') || (*s == 'X'))) { - c = s[1]; - s += 2; - } - - cutoff = ULONG_MAX / base; - cutlim = ULONG_MAX % base; - acc = 0UL; - any = 0; - digit = hex_digit_value(c); - while (digit >= 0) { - if ((acc > cutoff) || ((acc == cutoff) && ((uint64_t)digit > cutlim))) { - any = -1; - break; - } else { - acc *= base; - acc += (uint64_t)digit; - } - - c = *s; - s++; - digit = hex_digit_value(c); - } - - if (any < 0) { - acc = ULONG_MAX; - } - return acc; + return strtoul(nptr, NULL, 16); } -char *strchr(char *s_arg, char ch) +char *strchr(const char *s_arg, char ch) { - char *s = s_arg; + const char *s = s_arg; while ((*s != '\0') && (*s != ch)) { ++s; } - return ((*s) != '\0') ? s : NULL; + return ((*s) != '\0') ? (char *)s : NULL; +} + +size_t strlen(const char *str) +{ + unsigned long ret; + + for (ret = 0; *str != '\0'; str++) { + ret++; + } + + return ret; +} + +size_t strnlen(const char *str, size_t count) +{ + unsigned long ret; + + for (ret = 0; (*str != '\0') && (ret < count); str++) { + ret++; + } + + return ret; +} + +char *strrchr(const char *s, char ch) +{ + const char *last = s + strlen(s); + while (last > s && *last != ch) { + last--; + } + + return (*last != ch) ? NULL : (char *)last; +} + +char *strcpy(char *d, const char *s) +{ + char *ret = d; + while ((*d++ = *s++) != '\0') { } + return ret; } /*