1 // SPDX-License-Identifier: GPL-2.0
2 #define IN_BOOT_STRING_C 1
3 #include <linux/ctype.h>
4 #include <linux/kernel.h>
5 #include <linux/errno.h>
6 #undef CONFIG_KASAN
7 #undef CONFIG_KASAN_GENERIC
8 #undef CONFIG_KMSAN
9 #include "../lib/string.c"
10
11 /*
12 * Duplicate some functions from the common lib/string.c
13 * instead of fully including it.
14 */
15
strncmp(const char * cs,const char * ct,size_t count)16 int strncmp(const char *cs, const char *ct, size_t count)
17 {
18 unsigned char c1, c2;
19
20 while (count) {
21 c1 = *cs++;
22 c2 = *ct++;
23 if (c1 != c2)
24 return c1 < c2 ? -1 : 1;
25 if (!c1)
26 break;
27 count--;
28 }
29 return 0;
30 }
31
sized_strscpy(char * dst,const char * src,size_t count)32 ssize_t sized_strscpy(char *dst, const char *src, size_t count)
33 {
34 size_t len;
35
36 if (count == 0)
37 return -E2BIG;
38 len = strnlen(src, count - 1);
39 memcpy(dst, src, len);
40 dst[len] = '\0';
41 return src[len] ? -E2BIG : len;
42 }
43
memset64(uint64_t * s,uint64_t v,size_t count)44 void *memset64(uint64_t *s, uint64_t v, size_t count)
45 {
46 uint64_t *xs = s;
47
48 while (count--)
49 *xs++ = v;
50 return s;
51 }
52
skip_spaces(const char * str)53 char *skip_spaces(const char *str)
54 {
55 while (isspace(*str))
56 ++str;
57 return (char *)str;
58 }
59
strim(char * s)60 char *strim(char *s)
61 {
62 size_t size;
63 char *end;
64
65 size = strlen(s);
66 if (!size)
67 return s;
68
69 end = s + size - 1;
70 while (end >= s && isspace(*end))
71 end--;
72 *(end + 1) = '\0';
73
74 return skip_spaces(s);
75 }
76
77 /* Works only for digits and letters, but small and fast */
78 #define TOLOWER(x) ((x) | 0x20)
79
simple_guess_base(const char * cp)80 static unsigned int simple_guess_base(const char *cp)
81 {
82 if (cp[0] == '0') {
83 if (TOLOWER(cp[1]) == 'x' && isxdigit(cp[2]))
84 return 16;
85 else
86 return 8;
87 } else {
88 return 10;
89 }
90 }
91
92 /**
93 * simple_strtoull - convert a string to an unsigned long long
94 * @cp: The start of the string
95 * @endp: A pointer to the end of the parsed string will be placed here
96 * @base: The number base to use
97 */
98
simple_strtoull(const char * cp,char ** endp,unsigned int base)99 unsigned long long simple_strtoull(const char *cp, char **endp,
100 unsigned int base)
101 {
102 unsigned long long result = 0;
103
104 if (!base)
105 base = simple_guess_base(cp);
106
107 if (base == 16 && cp[0] == '0' && TOLOWER(cp[1]) == 'x')
108 cp += 2;
109
110 while (isxdigit(*cp)) {
111 unsigned int value;
112
113 value = isdigit(*cp) ? *cp - '0' : TOLOWER(*cp) - 'a' + 10;
114 if (value >= base)
115 break;
116 result = result * base + value;
117 cp++;
118 }
119 if (endp)
120 *endp = (char *)cp;
121
122 return result;
123 }
124
simple_strtol(const char * cp,char ** endp,unsigned int base)125 long simple_strtol(const char *cp, char **endp, unsigned int base)
126 {
127 if (*cp == '-')
128 return -simple_strtoull(cp + 1, endp, base);
129
130 return simple_strtoull(cp, endp, base);
131 }
132
kstrtobool(const char * s,bool * res)133 int kstrtobool(const char *s, bool *res)
134 {
135 if (!s)
136 return -EINVAL;
137
138 switch (s[0]) {
139 case 'y':
140 case 'Y':
141 case '1':
142 *res = true;
143 return 0;
144 case 'n':
145 case 'N':
146 case '0':
147 *res = false;
148 return 0;
149 case 'o':
150 case 'O':
151 switch (s[1]) {
152 case 'n':
153 case 'N':
154 *res = true;
155 return 0;
156 case 'f':
157 case 'F':
158 *res = false;
159 return 0;
160 default:
161 break;
162 }
163 default:
164 break;
165 }
166
167 return -EINVAL;
168 }
169