Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  * Misc librarized functions for cmdline poking.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #include <linux/ctype.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <asm/setup.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) static inline int myisspace(u8 c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) 	return c <= ' ';	/* Close enough approximation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17)  * Find a boolean option (like quiet,noapic,nosmp....)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19)  * @cmdline: the cmdline string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20)  * @option: option string to look for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22)  * Returns the position of that @option (starts counting with 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23)  * or 0 on not found.  @option will only be found if it is found
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24)  * as an entire word in @cmdline.  For instance, if @option="car"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25)  * then a cmdline which contains "cart" will not match.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) __cmdline_find_option_bool(const char *cmdline, int max_cmdline_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 			   const char *option)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 	char c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 	int pos = 0, wstart = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 	const char *opptr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 	enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 		st_wordstart = 0,	/* Start of word/after whitespace */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 		st_wordcmp,	/* Comparing this word */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 		st_wordskip,	/* Miscompare, skip */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 	} state = st_wordstart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	if (!cmdline)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 		return -1;      /* No command line */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 	 * This 'pos' check ensures we do not overrun
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 	 * a non-NULL-terminated 'cmdline'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	while (pos < max_cmdline_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 		c = *(char *)cmdline++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 		pos++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 		switch (state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 		case st_wordstart:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 			if (!c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 				return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 			else if (myisspace(c))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 			state = st_wordcmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 			opptr = option;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 			wstart = pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 			fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 		case st_wordcmp:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 			if (!*opptr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 				/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 				 * We matched all the way to the end of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 				 * option we were looking for.  If the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 				 * command-line has a space _or_ ends, then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 				 * we matched!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 				 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 				if (!c || myisspace(c))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 					return wstart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 				/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 				 * We hit the end of the option, but _not_
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 				 * the end of a word on the cmdline.  Not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 				 * a match.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 				 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 			} else if (!c) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 				/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 				 * Hit the NULL terminator on the end of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 				 * cmdline.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 				 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 				return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 			} else if (c == *opptr++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 				/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 				 * We are currently matching, so continue
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 				 * to the next character on the cmdline.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 				 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 			state = st_wordskip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 			fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 		case st_wordskip:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 			if (!c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 				return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 			else if (myisspace(c))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 				state = st_wordstart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	return 0;	/* Buffer overrun */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)  * Find a non-boolean option (i.e. option=argument). In accordance with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)  * standard Linux practice, if this option is repeated, this returns the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)  * last instance on the command line.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)  * @cmdline: the cmdline string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)  * @max_cmdline_size: the maximum size of cmdline
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)  * @option: option string to look for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)  * @buffer: memory buffer to return the option argument
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)  * @bufsize: size of the supplied memory buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)  * Returns the length of the argument (regardless of if it was
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)  * truncated to fit in the buffer), or -1 on not found.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) __cmdline_find_option(const char *cmdline, int max_cmdline_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 		      const char *option, char *buffer, int bufsize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	char c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	int pos = 0, len = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	const char *opptr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	char *bufptr = buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 		st_wordstart = 0,	/* Start of word/after whitespace */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 		st_wordcmp,	/* Comparing this word */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 		st_wordskip,	/* Miscompare, skip */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 		st_bufcpy,	/* Copying this to buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	} state = st_wordstart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 	if (!cmdline)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 		return -1;      /* No command line */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	 * This 'pos' check ensures we do not overrun
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	 * a non-NULL-terminated 'cmdline'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	while (pos++ < max_cmdline_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 		c = *(char *)cmdline++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 		if (!c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 		switch (state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 		case st_wordstart:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 			if (myisspace(c))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 			state = st_wordcmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 			opptr = option;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 			fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 		case st_wordcmp:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 			if ((c == '=') && !*opptr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 				/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 				 * We matched all the way to the end of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 				 * option we were looking for, prepare to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 				 * copy the argument.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 				 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 				len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 				bufptr = buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 				state = st_bufcpy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 			} else if (c == *opptr++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 				/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 				 * We are currently matching, so continue
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 				 * to the next character on the cmdline.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 				 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 			state = st_wordskip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 			fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 		case st_wordskip:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 			if (myisspace(c))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 				state = st_wordstart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 		case st_bufcpy:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 			if (myisspace(c)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 				state = st_wordstart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 			} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 				/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 				 * Increment len, but don't overrun the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 				 * supplied buffer and leave room for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 				 * NULL terminator.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 				 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 				if (++len < bufsize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 					*bufptr++ = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 	if (bufsize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 		*bufptr = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 	return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) int cmdline_find_option_bool(const char *cmdline, const char *option)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 	return __cmdline_find_option_bool(cmdline, COMMAND_LINE_SIZE, option);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) int cmdline_find_option(const char *cmdline, const char *option, char *buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 			int bufsize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 	return __cmdline_find_option(cmdline, COMMAND_LINE_SIZE, option,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 				     buffer, bufsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) }