xref: /kernel/linux/linux-5.10/lib/kstrtox.c (revision 8c2ecf20)
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