|  | // SPDX-License-Identifier: GPL-2.0-only | 
|  | /* -*- linux-c -*- ------------------------------------------------------- * | 
|  | * | 
|  | *   Copyright (C) 1991, 1992 Linus Torvalds | 
|  | *   Copyright 2007 rPath, Inc. - All Rights Reserved | 
|  | * | 
|  | * ----------------------------------------------------------------------- */ | 
|  |  | 
|  | /* | 
|  | * Very basic string functions | 
|  | */ | 
|  |  | 
|  | #include <linux/types.h> | 
|  | #include <linux/compiler.h> | 
|  | #include <linux/errno.h> | 
|  | #include <linux/limits.h> | 
|  | #include <asm/asm.h> | 
|  | #include "ctype.h" | 
|  | #include "string.h" | 
|  |  | 
|  | #define KSTRTOX_OVERFLOW       (1U << 31) | 
|  |  | 
|  | /* | 
|  | * Undef these macros so that the functions that we provide | 
|  | * here will have the correct names regardless of how string.h | 
|  | * may have chosen to #define them. | 
|  | */ | 
|  | #undef memcpy | 
|  | #undef memset | 
|  | #undef memcmp | 
|  |  | 
|  | int memcmp(const void *s1, const void *s2, size_t len) | 
|  | { | 
|  | bool diff; | 
|  | asm("repe; cmpsb" CC_SET(nz) | 
|  | : CC_OUT(nz) (diff), "+D" (s1), "+S" (s2), "+c" (len)); | 
|  | return diff; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Clang may lower `memcmp == 0` to `bcmp == 0`. | 
|  | */ | 
|  | int bcmp(const void *s1, const void *s2, size_t len) | 
|  | { | 
|  | return memcmp(s1, s2, len); | 
|  | } | 
|  |  | 
|  | int strcmp(const char *str1, const char *str2) | 
|  | { | 
|  | const unsigned char *s1 = (const unsigned char *)str1; | 
|  | const unsigned char *s2 = (const unsigned char *)str2; | 
|  | int delta = 0; | 
|  |  | 
|  | while (*s1 || *s2) { | 
|  | delta = *s1 - *s2; | 
|  | if (delta) | 
|  | return delta; | 
|  | s1++; | 
|  | s2++; | 
|  | } | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | int strncmp(const char *cs, const char *ct, size_t count) | 
|  | { | 
|  | unsigned char c1, c2; | 
|  |  | 
|  | while (count) { | 
|  | c1 = *cs++; | 
|  | c2 = *ct++; | 
|  | if (c1 != c2) | 
|  | return c1 < c2 ? -1 : 1; | 
|  | if (!c1) | 
|  | break; | 
|  | count--; | 
|  | } | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | size_t strnlen(const char *s, size_t maxlen) | 
|  | { | 
|  | const char *es = s; | 
|  | while (*es && maxlen) { | 
|  | es++; | 
|  | maxlen--; | 
|  | } | 
|  |  | 
|  | return (es - s); | 
|  | } | 
|  |  | 
|  | unsigned int atou(const char *s) | 
|  | { | 
|  | unsigned int i = 0; | 
|  | while (isdigit(*s)) | 
|  | i = i * 10 + (*s++ - '0'); | 
|  | return i; | 
|  | } | 
|  |  | 
|  | /* Works only for digits and letters, but small and fast */ | 
|  | #define TOLOWER(x) ((x) | 0x20) | 
|  |  | 
|  | static unsigned int simple_guess_base(const char *cp) | 
|  | { | 
|  | if (cp[0] == '0') { | 
|  | if (TOLOWER(cp[1]) == 'x' && isxdigit(cp[2])) | 
|  | return 16; | 
|  | else | 
|  | return 8; | 
|  | } else { | 
|  | return 10; | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * simple_strtoull - convert a string to an unsigned long long | 
|  | * @cp: The start of the string | 
|  | * @endp: A pointer to the end of the parsed string will be placed here | 
|  | * @base: The number base to use | 
|  | */ | 
|  | unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int base) | 
|  | { | 
|  | unsigned long long result = 0; | 
|  |  | 
|  | if (!base) | 
|  | base = simple_guess_base(cp); | 
|  |  | 
|  | if (base == 16 && cp[0] == '0' && TOLOWER(cp[1]) == 'x') | 
|  | cp += 2; | 
|  |  | 
|  | while (isxdigit(*cp)) { | 
|  | unsigned int value; | 
|  |  | 
|  | value = isdigit(*cp) ? *cp - '0' : TOLOWER(*cp) - 'a' + 10; | 
|  | if (value >= base) | 
|  | break; | 
|  | result = result * base + value; | 
|  | cp++; | 
|  | } | 
|  | if (endp) | 
|  | *endp = (char *)cp; | 
|  |  | 
|  | return result; | 
|  | } | 
|  |  | 
|  | long simple_strtol(const char *cp, char **endp, unsigned int base) | 
|  | { | 
|  | if (*cp == '-') | 
|  | return -simple_strtoull(cp + 1, endp, base); | 
|  |  | 
|  | return simple_strtoull(cp, endp, base); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * strlen - Find the length of a string | 
|  | * @s: The string to be sized | 
|  | */ | 
|  | size_t strlen(const char *s) | 
|  | { | 
|  | const char *sc; | 
|  |  | 
|  | for (sc = s; *sc != '\0'; ++sc) | 
|  | /* nothing */; | 
|  | return sc - s; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * strstr - Find the first substring in a %NUL terminated string | 
|  | * @s1: The string to be searched | 
|  | * @s2: The string to search for | 
|  | */ | 
|  | char *strstr(const char *s1, const char *s2) | 
|  | { | 
|  | size_t l1, l2; | 
|  |  | 
|  | l2 = strlen(s2); | 
|  | if (!l2) | 
|  | return (char *)s1; | 
|  | l1 = strlen(s1); | 
|  | while (l1 >= l2) { | 
|  | l1--; | 
|  | if (!memcmp(s1, s2, l2)) | 
|  | return (char *)s1; | 
|  | s1++; | 
|  | } | 
|  | return NULL; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * strchr - Find the first occurrence of the character c in the string s. | 
|  | * @s: the string to be searched | 
|  | * @c: the character to search for | 
|  | */ | 
|  | char *strchr(const char *s, int c) | 
|  | { | 
|  | while (*s != (char)c) | 
|  | if (*s++ == '\0') | 
|  | return NULL; | 
|  | return (char *)s; | 
|  | } | 
|  |  | 
|  | static inline u64 __div_u64_rem(u64 dividend, u32 divisor, u32 *remainder) | 
|  | { | 
|  | union { | 
|  | u64 v64; | 
|  | u32 v32[2]; | 
|  | } d = { dividend }; | 
|  | u32 upper; | 
|  |  | 
|  | upper = d.v32[1]; | 
|  | d.v32[1] = 0; | 
|  | if (upper >= divisor) { | 
|  | d.v32[1] = upper / divisor; | 
|  | upper %= divisor; | 
|  | } | 
|  | asm ("divl %2" : "=a" (d.v32[0]), "=d" (*remainder) : | 
|  | "rm" (divisor), "0" (d.v32[0]), "1" (upper)); | 
|  | return d.v64; | 
|  | } | 
|  |  | 
|  | static inline u64 __div_u64(u64 dividend, u32 divisor) | 
|  | { | 
|  | u32 remainder; | 
|  |  | 
|  | return __div_u64_rem(dividend, divisor, &remainder); | 
|  | } | 
|  |  | 
|  | static inline char _tolower(const char c) | 
|  | { | 
|  | return c | 0x20; | 
|  | } | 
|  |  | 
|  | static const char *_parse_integer_fixup_radix(const char *s, unsigned int *base) | 
|  | { | 
|  | if (*base == 0) { | 
|  | if (s[0] == '0') { | 
|  | if (_tolower(s[1]) == 'x' && isxdigit(s[2])) | 
|  | *base = 16; | 
|  | else | 
|  | *base = 8; | 
|  | } else | 
|  | *base = 10; | 
|  | } | 
|  | if (*base == 16 && s[0] == '0' && _tolower(s[1]) == 'x') | 
|  | s += 2; | 
|  | return s; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Convert non-negative integer string representation in explicitly given radix | 
|  | * to an integer. | 
|  | * Return number of characters consumed maybe or-ed with overflow bit. | 
|  | * If overflow occurs, result integer (incorrect) is still returned. | 
|  | * | 
|  | * Don't you dare use this function. | 
|  | */ | 
|  | static unsigned int _parse_integer(const char *s, | 
|  | unsigned int base, | 
|  | unsigned long long *p) | 
|  | { | 
|  | unsigned long long res; | 
|  | unsigned int rv; | 
|  |  | 
|  | res = 0; | 
|  | rv = 0; | 
|  | while (1) { | 
|  | unsigned int c = *s; | 
|  | unsigned int lc = c | 0x20; /* don't tolower() this line */ | 
|  | unsigned int val; | 
|  |  | 
|  | if ('0' <= c && c <= '9') | 
|  | val = c - '0'; | 
|  | else if ('a' <= lc && lc <= 'f') | 
|  | val = lc - 'a' + 10; | 
|  | else | 
|  | break; | 
|  |  | 
|  | if (val >= base) | 
|  | break; | 
|  | /* | 
|  | * Check for overflow only if we are within range of | 
|  | * it in the max base we support (16) | 
|  | */ | 
|  | if (unlikely(res & (~0ull << 60))) { | 
|  | if (res > __div_u64(ULLONG_MAX - val, base)) | 
|  | rv |= KSTRTOX_OVERFLOW; | 
|  | } | 
|  | res = res * base + val; | 
|  | rv++; | 
|  | s++; | 
|  | } | 
|  | *p = res; | 
|  | return rv; | 
|  | } | 
|  |  | 
|  | static int _kstrtoull(const char *s, unsigned int base, unsigned long long *res) | 
|  | { | 
|  | unsigned long long _res; | 
|  | unsigned int rv; | 
|  |  | 
|  | s = _parse_integer_fixup_radix(s, &base); | 
|  | rv = _parse_integer(s, base, &_res); | 
|  | if (rv & KSTRTOX_OVERFLOW) | 
|  | return -ERANGE; | 
|  | if (rv == 0) | 
|  | return -EINVAL; | 
|  | s += rv; | 
|  | if (*s == '\n') | 
|  | s++; | 
|  | if (*s) | 
|  | return -EINVAL; | 
|  | *res = _res; | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * kstrtoull - convert a string to an unsigned long long | 
|  | * @s: The start of the string. The string must be null-terminated, and may also | 
|  | *  include a single newline before its terminating null. The first character | 
|  | *  may also be a plus sign, but not a minus sign. | 
|  | * @base: The number base to use. The maximum supported base is 16. If base is | 
|  | *  given as 0, then the base of the string is automatically detected with the | 
|  | *  conventional semantics - If it begins with 0x the number will be parsed as a | 
|  | *  hexadecimal (case insensitive), if it otherwise begins with 0, it will be | 
|  | *  parsed as an octal number. Otherwise it will be parsed as a decimal. | 
|  | * @res: Where to write the result of the conversion on success. | 
|  | * | 
|  | * Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error. | 
|  | * Used as a replacement for the obsolete simple_strtoull. Return code must | 
|  | * be checked. | 
|  | */ | 
|  | int kstrtoull(const char *s, unsigned int base, unsigned long long *res) | 
|  | { | 
|  | if (s[0] == '+') | 
|  | s++; | 
|  | return _kstrtoull(s, base, res); | 
|  | } | 
|  |  | 
|  | static int _kstrtoul(const char *s, unsigned int base, unsigned long *res) | 
|  | { | 
|  | unsigned long long tmp; | 
|  | int rv; | 
|  |  | 
|  | rv = kstrtoull(s, base, &tmp); | 
|  | if (rv < 0) | 
|  | return rv; | 
|  | if (tmp != (unsigned long)tmp) | 
|  | return -ERANGE; | 
|  | *res = tmp; | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * kstrtoul - convert a string to an unsigned long | 
|  | * @s: The start of the string. The string must be null-terminated, and may also | 
|  | *  include a single newline before its terminating null. The first character | 
|  | *  may also be a plus sign, but not a minus sign. | 
|  | * @base: The number base to use. The maximum supported base is 16. If base is | 
|  | *  given as 0, then the base of the string is automatically detected with the | 
|  | *  conventional semantics - If it begins with 0x the number will be parsed as a | 
|  | *  hexadecimal (case insensitive), if it otherwise begins with 0, it will be | 
|  | *  parsed as an octal number. Otherwise it will be parsed as a decimal. | 
|  | * @res: Where to write the result of the conversion on success. | 
|  | * | 
|  | * Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error. | 
|  | * Used as a replacement for the simple_strtoull. | 
|  | */ | 
|  | int boot_kstrtoul(const char *s, unsigned int base, unsigned long *res) | 
|  | { | 
|  | /* | 
|  | * We want to shortcut function call, but | 
|  | * __builtin_types_compatible_p(unsigned long, unsigned long long) = 0. | 
|  | */ | 
|  | if (sizeof(unsigned long) == sizeof(unsigned long long) && | 
|  | __alignof__(unsigned long) == __alignof__(unsigned long long)) | 
|  | return kstrtoull(s, base, (unsigned long long *)res); | 
|  | else | 
|  | return _kstrtoul(s, base, res); | 
|  | } |