18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Convert integer string representation to an integer. 48c2ecf20Sopenharmony_ci * If an integer doesn't fit into specified type, -E is returned. 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Integer starts with optional sign. 78c2ecf20Sopenharmony_ci * kstrtou*() functions do not accept sign "-". 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * Radix 0 means autodetection: leading "0x" implies radix 16, 108c2ecf20Sopenharmony_ci * leading "0" implies radix 8, otherwise radix is 10. 118c2ecf20Sopenharmony_ci * Autodetection hints work after optional sign, but not before. 128c2ecf20Sopenharmony_ci * 138c2ecf20Sopenharmony_ci * If -E is returned, result is not touched. 148c2ecf20Sopenharmony_ci */ 158c2ecf20Sopenharmony_ci#include <linux/ctype.h> 168c2ecf20Sopenharmony_ci#include <linux/errno.h> 178c2ecf20Sopenharmony_ci#include <linux/export.h> 188c2ecf20Sopenharmony_ci#include <linux/kstrtox.h> 198c2ecf20Sopenharmony_ci#include <linux/math64.h> 208c2ecf20Sopenharmony_ci#include <linux/types.h> 218c2ecf20Sopenharmony_ci#include <linux/uaccess.h> 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci#include "kstrtox.h" 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ciconst char *_parse_integer_fixup_radix(const char *s, unsigned int *base) 268c2ecf20Sopenharmony_ci{ 278c2ecf20Sopenharmony_ci if (*base == 0) { 288c2ecf20Sopenharmony_ci if (s[0] == '0') { 298c2ecf20Sopenharmony_ci if (_tolower(s[1]) == 'x' && isxdigit(s[2])) 308c2ecf20Sopenharmony_ci *base = 16; 318c2ecf20Sopenharmony_ci else 328c2ecf20Sopenharmony_ci *base = 8; 338c2ecf20Sopenharmony_ci } else 348c2ecf20Sopenharmony_ci *base = 10; 358c2ecf20Sopenharmony_ci } 368c2ecf20Sopenharmony_ci if (*base == 16 && s[0] == '0' && _tolower(s[1]) == 'x') 378c2ecf20Sopenharmony_ci s += 2; 388c2ecf20Sopenharmony_ci return s; 398c2ecf20Sopenharmony_ci} 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci/* 428c2ecf20Sopenharmony_ci * Convert non-negative integer string representation in explicitly given radix 438c2ecf20Sopenharmony_ci * to an integer. A maximum of max_chars characters will be converted. 448c2ecf20Sopenharmony_ci * 458c2ecf20Sopenharmony_ci * Return number of characters consumed maybe or-ed with overflow bit. 468c2ecf20Sopenharmony_ci * If overflow occurs, result integer (incorrect) is still returned. 478c2ecf20Sopenharmony_ci * 488c2ecf20Sopenharmony_ci * Don't you dare use this function. 498c2ecf20Sopenharmony_ci */ 508c2ecf20Sopenharmony_ciunsigned int _parse_integer_limit(const char *s, unsigned int base, unsigned long long *p, 518c2ecf20Sopenharmony_ci size_t max_chars) 528c2ecf20Sopenharmony_ci{ 538c2ecf20Sopenharmony_ci unsigned long long res; 548c2ecf20Sopenharmony_ci unsigned int rv; 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci res = 0; 578c2ecf20Sopenharmony_ci rv = 0; 588c2ecf20Sopenharmony_ci while (max_chars--) { 598c2ecf20Sopenharmony_ci unsigned int c = *s; 608c2ecf20Sopenharmony_ci unsigned int lc = c | 0x20; /* don't tolower() this line */ 618c2ecf20Sopenharmony_ci unsigned int val; 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci if ('0' <= c && c <= '9') 648c2ecf20Sopenharmony_ci val = c - '0'; 658c2ecf20Sopenharmony_ci else if ('a' <= lc && lc <= 'f') 668c2ecf20Sopenharmony_ci val = lc - 'a' + 10; 678c2ecf20Sopenharmony_ci else 688c2ecf20Sopenharmony_ci break; 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci if (val >= base) 718c2ecf20Sopenharmony_ci break; 728c2ecf20Sopenharmony_ci /* 738c2ecf20Sopenharmony_ci * Check for overflow only if we are within range of 748c2ecf20Sopenharmony_ci * it in the max base we support (16) 758c2ecf20Sopenharmony_ci */ 768c2ecf20Sopenharmony_ci if (unlikely(res & (~0ull << 60))) { 778c2ecf20Sopenharmony_ci if (res > div_u64(ULLONG_MAX - val, base)) 788c2ecf20Sopenharmony_ci rv |= KSTRTOX_OVERFLOW; 798c2ecf20Sopenharmony_ci } 808c2ecf20Sopenharmony_ci res = res * base + val; 818c2ecf20Sopenharmony_ci rv++; 828c2ecf20Sopenharmony_ci s++; 838c2ecf20Sopenharmony_ci } 848c2ecf20Sopenharmony_ci *p = res; 858c2ecf20Sopenharmony_ci return rv; 868c2ecf20Sopenharmony_ci} 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ciunsigned int _parse_integer(const char *s, unsigned int base, unsigned long long *p) 898c2ecf20Sopenharmony_ci{ 908c2ecf20Sopenharmony_ci return _parse_integer_limit(s, base, p, INT_MAX); 918c2ecf20Sopenharmony_ci} 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_cistatic int _kstrtoull(const char *s, unsigned int base, unsigned long long *res) 948c2ecf20Sopenharmony_ci{ 958c2ecf20Sopenharmony_ci unsigned long long _res; 968c2ecf20Sopenharmony_ci unsigned int rv; 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci s = _parse_integer_fixup_radix(s, &base); 998c2ecf20Sopenharmony_ci rv = _parse_integer(s, base, &_res); 1008c2ecf20Sopenharmony_ci if (rv & KSTRTOX_OVERFLOW) 1018c2ecf20Sopenharmony_ci return -ERANGE; 1028c2ecf20Sopenharmony_ci if (rv == 0) 1038c2ecf20Sopenharmony_ci return -EINVAL; 1048c2ecf20Sopenharmony_ci s += rv; 1058c2ecf20Sopenharmony_ci if (*s == '\n') 1068c2ecf20Sopenharmony_ci s++; 1078c2ecf20Sopenharmony_ci if (*s) 1088c2ecf20Sopenharmony_ci return -EINVAL; 1098c2ecf20Sopenharmony_ci *res = _res; 1108c2ecf20Sopenharmony_ci return 0; 1118c2ecf20Sopenharmony_ci} 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci/** 1148c2ecf20Sopenharmony_ci * kstrtoull - convert a string to an unsigned long long 1158c2ecf20Sopenharmony_ci * @s: The start of the string. The string must be null-terminated, and may also 1168c2ecf20Sopenharmony_ci * include a single newline before its terminating null. The first character 1178c2ecf20Sopenharmony_ci * may also be a plus sign, but not a minus sign. 1188c2ecf20Sopenharmony_ci * @base: The number base to use. The maximum supported base is 16. If base is 1198c2ecf20Sopenharmony_ci * given as 0, then the base of the string is automatically detected with the 1208c2ecf20Sopenharmony_ci * conventional semantics - If it begins with 0x the number will be parsed as a 1218c2ecf20Sopenharmony_ci * hexadecimal (case insensitive), if it otherwise begins with 0, it will be 1228c2ecf20Sopenharmony_ci * parsed as an octal number. Otherwise it will be parsed as a decimal. 1238c2ecf20Sopenharmony_ci * @res: Where to write the result of the conversion on success. 1248c2ecf20Sopenharmony_ci * 1258c2ecf20Sopenharmony_ci * Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error. 1268c2ecf20Sopenharmony_ci * Preferred over simple_strtoull(). Return code must be checked. 1278c2ecf20Sopenharmony_ci */ 1288c2ecf20Sopenharmony_ciint kstrtoull(const char *s, unsigned int base, unsigned long long *res) 1298c2ecf20Sopenharmony_ci{ 1308c2ecf20Sopenharmony_ci if (s[0] == '+') 1318c2ecf20Sopenharmony_ci s++; 1328c2ecf20Sopenharmony_ci return _kstrtoull(s, base, res); 1338c2ecf20Sopenharmony_ci} 1348c2ecf20Sopenharmony_ciEXPORT_SYMBOL(kstrtoull); 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci/** 1378c2ecf20Sopenharmony_ci * kstrtoll - convert a string to a long long 1388c2ecf20Sopenharmony_ci * @s: The start of the string. The string must be null-terminated, and may also 1398c2ecf20Sopenharmony_ci * include a single newline before its terminating null. The first character 1408c2ecf20Sopenharmony_ci * may also be a plus sign or a minus sign. 1418c2ecf20Sopenharmony_ci * @base: The number base to use. The maximum supported base is 16. If base is 1428c2ecf20Sopenharmony_ci * given as 0, then the base of the string is automatically detected with the 1438c2ecf20Sopenharmony_ci * conventional semantics - If it begins with 0x the number will be parsed as a 1448c2ecf20Sopenharmony_ci * hexadecimal (case insensitive), if it otherwise begins with 0, it will be 1458c2ecf20Sopenharmony_ci * parsed as an octal number. Otherwise it will be parsed as a decimal. 1468c2ecf20Sopenharmony_ci * @res: Where to write the result of the conversion on success. 1478c2ecf20Sopenharmony_ci * 1488c2ecf20Sopenharmony_ci * Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error. 1498c2ecf20Sopenharmony_ci * Preferred over simple_strtoll(). Return code must be checked. 1508c2ecf20Sopenharmony_ci */ 1518c2ecf20Sopenharmony_ciint kstrtoll(const char *s, unsigned int base, long long *res) 1528c2ecf20Sopenharmony_ci{ 1538c2ecf20Sopenharmony_ci unsigned long long tmp; 1548c2ecf20Sopenharmony_ci int rv; 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci if (s[0] == '-') { 1578c2ecf20Sopenharmony_ci rv = _kstrtoull(s + 1, base, &tmp); 1588c2ecf20Sopenharmony_ci if (rv < 0) 1598c2ecf20Sopenharmony_ci return rv; 1608c2ecf20Sopenharmony_ci if ((long long)-tmp > 0) 1618c2ecf20Sopenharmony_ci return -ERANGE; 1628c2ecf20Sopenharmony_ci *res = -tmp; 1638c2ecf20Sopenharmony_ci } else { 1648c2ecf20Sopenharmony_ci rv = kstrtoull(s, base, &tmp); 1658c2ecf20Sopenharmony_ci if (rv < 0) 1668c2ecf20Sopenharmony_ci return rv; 1678c2ecf20Sopenharmony_ci if ((long long)tmp < 0) 1688c2ecf20Sopenharmony_ci return -ERANGE; 1698c2ecf20Sopenharmony_ci *res = tmp; 1708c2ecf20Sopenharmony_ci } 1718c2ecf20Sopenharmony_ci return 0; 1728c2ecf20Sopenharmony_ci} 1738c2ecf20Sopenharmony_ciEXPORT_SYMBOL(kstrtoll); 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci/* Internal, do not use. */ 1768c2ecf20Sopenharmony_ciint _kstrtoul(const char *s, unsigned int base, unsigned long *res) 1778c2ecf20Sopenharmony_ci{ 1788c2ecf20Sopenharmony_ci unsigned long long tmp; 1798c2ecf20Sopenharmony_ci int rv; 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci rv = kstrtoull(s, base, &tmp); 1828c2ecf20Sopenharmony_ci if (rv < 0) 1838c2ecf20Sopenharmony_ci return rv; 1848c2ecf20Sopenharmony_ci if (tmp != (unsigned long)tmp) 1858c2ecf20Sopenharmony_ci return -ERANGE; 1868c2ecf20Sopenharmony_ci *res = tmp; 1878c2ecf20Sopenharmony_ci return 0; 1888c2ecf20Sopenharmony_ci} 1898c2ecf20Sopenharmony_ciEXPORT_SYMBOL(_kstrtoul); 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci/* Internal, do not use. */ 1928c2ecf20Sopenharmony_ciint _kstrtol(const char *s, unsigned int base, long *res) 1938c2ecf20Sopenharmony_ci{ 1948c2ecf20Sopenharmony_ci long long tmp; 1958c2ecf20Sopenharmony_ci int rv; 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci rv = kstrtoll(s, base, &tmp); 1988c2ecf20Sopenharmony_ci if (rv < 0) 1998c2ecf20Sopenharmony_ci return rv; 2008c2ecf20Sopenharmony_ci if (tmp != (long)tmp) 2018c2ecf20Sopenharmony_ci return -ERANGE; 2028c2ecf20Sopenharmony_ci *res = tmp; 2038c2ecf20Sopenharmony_ci return 0; 2048c2ecf20Sopenharmony_ci} 2058c2ecf20Sopenharmony_ciEXPORT_SYMBOL(_kstrtol); 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci/** 2088c2ecf20Sopenharmony_ci * kstrtouint - convert a string to an unsigned int 2098c2ecf20Sopenharmony_ci * @s: The start of the string. The string must be null-terminated, and may also 2108c2ecf20Sopenharmony_ci * include a single newline before its terminating null. The first character 2118c2ecf20Sopenharmony_ci * may also be a plus sign, but not a minus sign. 2128c2ecf20Sopenharmony_ci * @base: The number base to use. The maximum supported base is 16. If base is 2138c2ecf20Sopenharmony_ci * given as 0, then the base of the string is automatically detected with the 2148c2ecf20Sopenharmony_ci * conventional semantics - If it begins with 0x the number will be parsed as a 2158c2ecf20Sopenharmony_ci * hexadecimal (case insensitive), if it otherwise begins with 0, it will be 2168c2ecf20Sopenharmony_ci * parsed as an octal number. Otherwise it will be parsed as a decimal. 2178c2ecf20Sopenharmony_ci * @res: Where to write the result of the conversion on success. 2188c2ecf20Sopenharmony_ci * 2198c2ecf20Sopenharmony_ci * Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error. 2208c2ecf20Sopenharmony_ci * Preferred over simple_strtoul(). Return code must be checked. 2218c2ecf20Sopenharmony_ci */ 2228c2ecf20Sopenharmony_ciint kstrtouint(const char *s, unsigned int base, unsigned int *res) 2238c2ecf20Sopenharmony_ci{ 2248c2ecf20Sopenharmony_ci unsigned long long tmp; 2258c2ecf20Sopenharmony_ci int rv; 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci rv = kstrtoull(s, base, &tmp); 2288c2ecf20Sopenharmony_ci if (rv < 0) 2298c2ecf20Sopenharmony_ci return rv; 2308c2ecf20Sopenharmony_ci if (tmp != (unsigned int)tmp) 2318c2ecf20Sopenharmony_ci return -ERANGE; 2328c2ecf20Sopenharmony_ci *res = tmp; 2338c2ecf20Sopenharmony_ci return 0; 2348c2ecf20Sopenharmony_ci} 2358c2ecf20Sopenharmony_ciEXPORT_SYMBOL(kstrtouint); 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci/** 2388c2ecf20Sopenharmony_ci * kstrtoint - convert a string to an int 2398c2ecf20Sopenharmony_ci * @s: The start of the string. The string must be null-terminated, and may also 2408c2ecf20Sopenharmony_ci * include a single newline before its terminating null. The first character 2418c2ecf20Sopenharmony_ci * may also be a plus sign or a minus sign. 2428c2ecf20Sopenharmony_ci * @base: The number base to use. The maximum supported base is 16. If base is 2438c2ecf20Sopenharmony_ci * given as 0, then the base of the string is automatically detected with the 2448c2ecf20Sopenharmony_ci * conventional semantics - If it begins with 0x the number will be parsed as a 2458c2ecf20Sopenharmony_ci * hexadecimal (case insensitive), if it otherwise begins with 0, it will be 2468c2ecf20Sopenharmony_ci * parsed as an octal number. Otherwise it will be parsed as a decimal. 2478c2ecf20Sopenharmony_ci * @res: Where to write the result of the conversion on success. 2488c2ecf20Sopenharmony_ci * 2498c2ecf20Sopenharmony_ci * Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error. 2508c2ecf20Sopenharmony_ci * Preferred over simple_strtol(). Return code must be checked. 2518c2ecf20Sopenharmony_ci */ 2528c2ecf20Sopenharmony_ciint kstrtoint(const char *s, unsigned int base, int *res) 2538c2ecf20Sopenharmony_ci{ 2548c2ecf20Sopenharmony_ci long long tmp; 2558c2ecf20Sopenharmony_ci int rv; 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci rv = kstrtoll(s, base, &tmp); 2588c2ecf20Sopenharmony_ci if (rv < 0) 2598c2ecf20Sopenharmony_ci return rv; 2608c2ecf20Sopenharmony_ci if (tmp != (int)tmp) 2618c2ecf20Sopenharmony_ci return -ERANGE; 2628c2ecf20Sopenharmony_ci *res = tmp; 2638c2ecf20Sopenharmony_ci return 0; 2648c2ecf20Sopenharmony_ci} 2658c2ecf20Sopenharmony_ciEXPORT_SYMBOL(kstrtoint); 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ciint kstrtou16(const char *s, unsigned int base, u16 *res) 2688c2ecf20Sopenharmony_ci{ 2698c2ecf20Sopenharmony_ci unsigned long long tmp; 2708c2ecf20Sopenharmony_ci int rv; 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci rv = kstrtoull(s, base, &tmp); 2738c2ecf20Sopenharmony_ci if (rv < 0) 2748c2ecf20Sopenharmony_ci return rv; 2758c2ecf20Sopenharmony_ci if (tmp != (u16)tmp) 2768c2ecf20Sopenharmony_ci return -ERANGE; 2778c2ecf20Sopenharmony_ci *res = tmp; 2788c2ecf20Sopenharmony_ci return 0; 2798c2ecf20Sopenharmony_ci} 2808c2ecf20Sopenharmony_ciEXPORT_SYMBOL(kstrtou16); 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ciint kstrtos16(const char *s, unsigned int base, s16 *res) 2838c2ecf20Sopenharmony_ci{ 2848c2ecf20Sopenharmony_ci long long tmp; 2858c2ecf20Sopenharmony_ci int rv; 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ci rv = kstrtoll(s, base, &tmp); 2888c2ecf20Sopenharmony_ci if (rv < 0) 2898c2ecf20Sopenharmony_ci return rv; 2908c2ecf20Sopenharmony_ci if (tmp != (s16)tmp) 2918c2ecf20Sopenharmony_ci return -ERANGE; 2928c2ecf20Sopenharmony_ci *res = tmp; 2938c2ecf20Sopenharmony_ci return 0; 2948c2ecf20Sopenharmony_ci} 2958c2ecf20Sopenharmony_ciEXPORT_SYMBOL(kstrtos16); 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ciint kstrtou8(const char *s, unsigned int base, u8 *res) 2988c2ecf20Sopenharmony_ci{ 2998c2ecf20Sopenharmony_ci unsigned long long tmp; 3008c2ecf20Sopenharmony_ci int rv; 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci rv = kstrtoull(s, base, &tmp); 3038c2ecf20Sopenharmony_ci if (rv < 0) 3048c2ecf20Sopenharmony_ci return rv; 3058c2ecf20Sopenharmony_ci if (tmp != (u8)tmp) 3068c2ecf20Sopenharmony_ci return -ERANGE; 3078c2ecf20Sopenharmony_ci *res = tmp; 3088c2ecf20Sopenharmony_ci return 0; 3098c2ecf20Sopenharmony_ci} 3108c2ecf20Sopenharmony_ciEXPORT_SYMBOL(kstrtou8); 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ciint kstrtos8(const char *s, unsigned int base, s8 *res) 3138c2ecf20Sopenharmony_ci{ 3148c2ecf20Sopenharmony_ci long long tmp; 3158c2ecf20Sopenharmony_ci int rv; 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci rv = kstrtoll(s, base, &tmp); 3188c2ecf20Sopenharmony_ci if (rv < 0) 3198c2ecf20Sopenharmony_ci return rv; 3208c2ecf20Sopenharmony_ci if (tmp != (s8)tmp) 3218c2ecf20Sopenharmony_ci return -ERANGE; 3228c2ecf20Sopenharmony_ci *res = tmp; 3238c2ecf20Sopenharmony_ci return 0; 3248c2ecf20Sopenharmony_ci} 3258c2ecf20Sopenharmony_ciEXPORT_SYMBOL(kstrtos8); 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci/** 3288c2ecf20Sopenharmony_ci * kstrtobool - convert common user inputs into boolean values 3298c2ecf20Sopenharmony_ci * @s: input string 3308c2ecf20Sopenharmony_ci * @res: result 3318c2ecf20Sopenharmony_ci * 3328c2ecf20Sopenharmony_ci * This routine returns 0 iff the first character is one of 'Yy1Nn0', or 3338c2ecf20Sopenharmony_ci * [oO][NnFf] for "on" and "off". Otherwise it will return -EINVAL. Value 3348c2ecf20Sopenharmony_ci * pointed to by res is updated upon finding a match. 3358c2ecf20Sopenharmony_ci */ 3368c2ecf20Sopenharmony_ciint kstrtobool(const char *s, bool *res) 3378c2ecf20Sopenharmony_ci{ 3388c2ecf20Sopenharmony_ci if (!s) 3398c2ecf20Sopenharmony_ci return -EINVAL; 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci switch (s[0]) { 3428c2ecf20Sopenharmony_ci case 'y': 3438c2ecf20Sopenharmony_ci case 'Y': 3448c2ecf20Sopenharmony_ci case '1': 3458c2ecf20Sopenharmony_ci *res = true; 3468c2ecf20Sopenharmony_ci return 0; 3478c2ecf20Sopenharmony_ci case 'n': 3488c2ecf20Sopenharmony_ci case 'N': 3498c2ecf20Sopenharmony_ci case '0': 3508c2ecf20Sopenharmony_ci *res = false; 3518c2ecf20Sopenharmony_ci return 0; 3528c2ecf20Sopenharmony_ci case 'o': 3538c2ecf20Sopenharmony_ci case 'O': 3548c2ecf20Sopenharmony_ci switch (s[1]) { 3558c2ecf20Sopenharmony_ci case 'n': 3568c2ecf20Sopenharmony_ci case 'N': 3578c2ecf20Sopenharmony_ci *res = true; 3588c2ecf20Sopenharmony_ci return 0; 3598c2ecf20Sopenharmony_ci case 'f': 3608c2ecf20Sopenharmony_ci case 'F': 3618c2ecf20Sopenharmony_ci *res = false; 3628c2ecf20Sopenharmony_ci return 0; 3638c2ecf20Sopenharmony_ci default: 3648c2ecf20Sopenharmony_ci break; 3658c2ecf20Sopenharmony_ci } 3668c2ecf20Sopenharmony_ci default: 3678c2ecf20Sopenharmony_ci break; 3688c2ecf20Sopenharmony_ci } 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci return -EINVAL; 3718c2ecf20Sopenharmony_ci} 3728c2ecf20Sopenharmony_ciEXPORT_SYMBOL(kstrtobool); 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci/* 3758c2ecf20Sopenharmony_ci * Since "base" would be a nonsense argument, this open-codes the 3768c2ecf20Sopenharmony_ci * _from_user helper instead of using the helper macro below. 3778c2ecf20Sopenharmony_ci */ 3788c2ecf20Sopenharmony_ciint kstrtobool_from_user(const char __user *s, size_t count, bool *res) 3798c2ecf20Sopenharmony_ci{ 3808c2ecf20Sopenharmony_ci /* Longest string needed to differentiate, newline, terminator */ 3818c2ecf20Sopenharmony_ci char buf[4]; 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_ci count = min(count, sizeof(buf) - 1); 3848c2ecf20Sopenharmony_ci if (copy_from_user(buf, s, count)) 3858c2ecf20Sopenharmony_ci return -EFAULT; 3868c2ecf20Sopenharmony_ci buf[count] = '\0'; 3878c2ecf20Sopenharmony_ci return kstrtobool(buf, res); 3888c2ecf20Sopenharmony_ci} 3898c2ecf20Sopenharmony_ciEXPORT_SYMBOL(kstrtobool_from_user); 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_ci#define kstrto_from_user(f, g, type) \ 3928c2ecf20Sopenharmony_ciint f(const char __user *s, size_t count, unsigned int base, type *res) \ 3938c2ecf20Sopenharmony_ci{ \ 3948c2ecf20Sopenharmony_ci /* sign, base 2 representation, newline, terminator */ \ 3958c2ecf20Sopenharmony_ci char buf[1 + sizeof(type) * 8 + 1 + 1]; \ 3968c2ecf20Sopenharmony_ci \ 3978c2ecf20Sopenharmony_ci count = min(count, sizeof(buf) - 1); \ 3988c2ecf20Sopenharmony_ci if (copy_from_user(buf, s, count)) \ 3998c2ecf20Sopenharmony_ci return -EFAULT; \ 4008c2ecf20Sopenharmony_ci buf[count] = '\0'; \ 4018c2ecf20Sopenharmony_ci return g(buf, base, res); \ 4028c2ecf20Sopenharmony_ci} \ 4038c2ecf20Sopenharmony_ciEXPORT_SYMBOL(f) 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_cikstrto_from_user(kstrtoull_from_user, kstrtoull, unsigned long long); 4068c2ecf20Sopenharmony_cikstrto_from_user(kstrtoll_from_user, kstrtoll, long long); 4078c2ecf20Sopenharmony_cikstrto_from_user(kstrtoul_from_user, kstrtoul, unsigned long); 4088c2ecf20Sopenharmony_cikstrto_from_user(kstrtol_from_user, kstrtol, long); 4098c2ecf20Sopenharmony_cikstrto_from_user(kstrtouint_from_user, kstrtouint, unsigned int); 4108c2ecf20Sopenharmony_cikstrto_from_user(kstrtoint_from_user, kstrtoint, int); 4118c2ecf20Sopenharmony_cikstrto_from_user(kstrtou16_from_user, kstrtou16, u16); 4128c2ecf20Sopenharmony_cikstrto_from_user(kstrtos16_from_user, kstrtos16, s16); 4138c2ecf20Sopenharmony_cikstrto_from_user(kstrtou8_from_user, kstrtou8, u8); 4148c2ecf20Sopenharmony_cikstrto_from_user(kstrtos8_from_user, kstrtos8, s8); 415