linux/arch/x86/boot/string.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/* -*- linux-c -*- ------------------------------------------------------- *
   3 *
   4 *   Copyright (C) 1991, 1992 Linus Torvalds
   5 *   Copyright 2007 rPath, Inc. - All Rights Reserved
   6 *
   7 * ----------------------------------------------------------------------- */
   8
   9/*
  10 * Very basic string functions
  11 */
  12
  13#include <linux/types.h>
  14#include <linux/compiler.h>
  15#include <linux/errno.h>
  16#include <linux/limits.h>
  17#include <asm/asm.h>
  18#include "ctype.h"
  19#include "string.h"
  20
  21#define KSTRTOX_OVERFLOW       (1U << 31)
  22
  23/*
  24 * Undef these macros so that the functions that we provide
  25 * here will have the correct names regardless of how string.h
  26 * may have chosen to #define them.
  27 */
  28#undef memcpy
  29#undef memset
  30#undef memcmp
  31
  32int memcmp(const void *s1, const void *s2, size_t len)
  33{
  34        bool diff;
  35        asm("repe; cmpsb" CC_SET(nz)
  36            : CC_OUT(nz) (diff), "+D" (s1), "+S" (s2), "+c" (len));
  37        return diff;
  38}
  39
  40/*
  41 * Clang may lower `memcmp == 0` to `bcmp == 0`.
  42 */
  43int bcmp(const void *s1, const void *s2, size_t len)
  44{
  45        return memcmp(s1, s2, len);
  46}
  47
  48int strcmp(const char *str1, const char *str2)
  49{
  50        const unsigned char *s1 = (const unsigned char *)str1;
  51        const unsigned char *s2 = (const unsigned char *)str2;
  52        int delta = 0;
  53
  54        while (*s1 || *s2) {
  55                delta = *s1 - *s2;
  56                if (delta)
  57                        return delta;
  58                s1++;
  59                s2++;
  60        }
  61        return 0;
  62}
  63
  64int strncmp(const char *cs, const char *ct, size_t count)
  65{
  66        unsigned char c1, c2;
  67
  68        while (count) {
  69                c1 = *cs++;
  70                c2 = *ct++;
  71                if (c1 != c2)
  72                        return c1 < c2 ? -1 : 1;
  73                if (!c1)
  74                        break;
  75                count--;
  76        }
  77        return 0;
  78}
  79
  80size_t strnlen(const char *s, size_t maxlen)
  81{
  82        const char *es = s;
  83        while (*es && maxlen) {
  84                es++;
  85                maxlen--;
  86        }
  87
  88        return (es - s);
  89}
  90
  91unsigned int atou(const char *s)
  92{
  93        unsigned int i = 0;
  94        while (isdigit(*s))
  95                i = i * 10 + (*s++ - '0');
  96        return i;
  97}
  98
  99/* Works only for digits and letters, but small and fast */
 100#define TOLOWER(x) ((x) | 0x20)
 101
 102static unsigned int simple_guess_base(const char *cp)
 103{
 104        if (cp[0] == '0') {
 105                if (TOLOWER(cp[1]) == 'x' && isxdigit(cp[2]))
 106                        return 16;
 107                else
 108                        return 8;
 109        } else {
 110                return 10;
 111        }
 112}
 113
 114/**
 115 * simple_strtoull - convert a string to an unsigned long long
 116 * @cp: The start of the string
 117 * @endp: A pointer to the end of the parsed string will be placed here
 118 * @base: The number base to use
 119 */
 120
 121unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int base)
 122{
 123        unsigned long long result = 0;
 124
 125        if (!base)
 126                base = simple_guess_base(cp);
 127
 128        if (base == 16 && cp[0] == '0' && TOLOWER(cp[1]) == 'x')
 129                cp += 2;
 130
 131        while (isxdigit(*cp)) {
 132                unsigned int value;
 133
 134                value = isdigit(*cp) ? *cp - '0' : TOLOWER(*cp) - 'a' + 10;
 135                if (value >= base)
 136                        break;
 137                result = result * base + value;
 138                cp++;
 139        }
 140        if (endp)
 141                *endp = (char *)cp;
 142
 143        return result;
 144}
 145
 146long simple_strtol(const char *cp, char **endp, unsigned int base)
 147{
 148        if (*cp == '-')
 149                return -simple_strtoull(cp + 1, endp, base);
 150
 151        return simple_strtoull(cp, endp, base);
 152}
 153
 154/**
 155 * strlen - Find the length of a string
 156 * @s: The string to be sized
 157 */
 158size_t strlen(const char *s)
 159{
 160        const char *sc;
 161
 162        for (sc = s; *sc != '\0'; ++sc)
 163                /* nothing */;
 164        return sc - s;
 165}
 166
 167/**
 168 * strstr - Find the first substring in a %NUL terminated string
 169 * @s1: The string to be searched
 170 * @s2: The string to search for
 171 */
 172char *strstr(const char *s1, const char *s2)
 173{
 174        size_t l1, l2;
 175
 176        l2 = strlen(s2);
 177        if (!l2)
 178                return (char *)s1;
 179        l1 = strlen(s1);
 180        while (l1 >= l2) {
 181                l1--;
 182                if (!memcmp(s1, s2, l2))
 183                        return (char *)s1;
 184                s1++;
 185        }
 186        return NULL;
 187}
 188
 189/**
 190 * strchr - Find the first occurrence of the character c in the string s.
 191 * @s: the string to be searched
 192 * @c: the character to search for
 193 */
 194char *strchr(const char *s, int c)
 195{
 196        while (*s != (char)c)
 197                if (*s++ == '\0')
 198                        return NULL;
 199        return (char *)s;
 200}
 201
 202static inline u64 __div_u64_rem(u64 dividend, u32 divisor, u32 *remainder)
 203{
 204        union {
 205                u64 v64;
 206                u32 v32[2];
 207        } d = { dividend };
 208        u32 upper;
 209
 210        upper = d.v32[1];
 211        d.v32[1] = 0;
 212        if (upper >= divisor) {
 213                d.v32[1] = upper / divisor;
 214                upper %= divisor;
 215        }
 216        asm ("divl %2" : "=a" (d.v32[0]), "=d" (*remainder) :
 217                "rm" (divisor), "0" (d.v32[0]), "1" (upper));
 218        return d.v64;
 219}
 220
 221static inline u64 __div_u64(u64 dividend, u32 divisor)
 222{
 223        u32 remainder;
 224
 225        return __div_u64_rem(dividend, divisor, &remainder);
 226}
 227
 228static inline char _tolower(const char c)
 229{
 230        return c | 0x20;
 231}
 232
 233static const char *_parse_integer_fixup_radix(const char *s, unsigned int *base)
 234{
 235        if (*base == 0) {
 236                if (s[0] == '0') {
 237                        if (_tolower(s[1]) == 'x' && isxdigit(s[2]))
 238                                *base = 16;
 239                        else
 240                                *base = 8;
 241                } else
 242                        *base = 10;
 243        }
 244        if (*base == 16 && s[0] == '0' && _tolower(s[1]) == 'x')
 245                s += 2;
 246        return s;
 247}
 248
 249/*
 250 * Convert non-negative integer string representation in explicitly given radix
 251 * to an integer.
 252 * Return number of characters consumed maybe or-ed with overflow bit.
 253 * If overflow occurs, result integer (incorrect) is still returned.
 254 *
 255 * Don't you dare use this function.
 256 */
 257static unsigned int _parse_integer(const char *s,
 258                                   unsigned int base,
 259                                   unsigned long long *p)
 260{
 261        unsigned long long res;
 262        unsigned int rv;
 263
 264        res = 0;
 265        rv = 0;
 266        while (1) {
 267                unsigned int c = *s;
 268                unsigned int lc = c | 0x20; /* don't tolower() this line */
 269                unsigned int val;
 270
 271                if ('0' <= c && c <= '9')
 272                        val = c - '0';
 273                else if ('a' <= lc && lc <= 'f')
 274                        val = lc - 'a' + 10;
 275                else
 276                        break;
 277
 278                if (val >= base)
 279                        break;
 280                /*
 281                 * Check for overflow only if we are within range of
 282                 * it in the max base we support (16)
 283                 */
 284                if (unlikely(res & (~0ull << 60))) {
 285                        if (res > __div_u64(ULLONG_MAX - val, base))
 286                                rv |= KSTRTOX_OVERFLOW;
 287                }
 288                res = res * base + val;
 289                rv++;
 290                s++;
 291        }
 292        *p = res;
 293        return rv;
 294}
 295
 296static int _kstrtoull(const char *s, unsigned int base, unsigned long long *res)
 297{
 298        unsigned long long _res;
 299        unsigned int rv;
 300
 301        s = _parse_integer_fixup_radix(s, &base);
 302        rv = _parse_integer(s, base, &_res);
 303        if (rv & KSTRTOX_OVERFLOW)
 304                return -ERANGE;
 305        if (rv == 0)
 306                return -EINVAL;
 307        s += rv;
 308        if (*s == '\n')
 309                s++;
 310        if (*s)
 311                return -EINVAL;
 312        *res = _res;
 313        return 0;
 314}
 315
 316/**
 317 * kstrtoull - convert a string to an unsigned long long
 318 * @s: The start of the string. The string must be null-terminated, and may also
 319 *  include a single newline before its terminating null. The first character
 320 *  may also be a plus sign, but not a minus sign.
 321 * @base: The number base to use. The maximum supported base is 16. If base is
 322 *  given as 0, then the base of the string is automatically detected with the
 323 *  conventional semantics - If it begins with 0x the number will be parsed as a
 324 *  hexadecimal (case insensitive), if it otherwise begins with 0, it will be
 325 *  parsed as an octal number. Otherwise it will be parsed as a decimal.
 326 * @res: Where to write the result of the conversion on success.
 327 *
 328 * Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error.
 329 * Used as a replacement for the obsolete simple_strtoull. Return code must
 330 * be checked.
 331 */
 332int kstrtoull(const char *s, unsigned int base, unsigned long long *res)
 333{
 334        if (s[0] == '+')
 335                s++;
 336        return _kstrtoull(s, base, res);
 337}
 338