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 * Simple command-line parser for early boot. 11 */ 12 13 #include "boot.h" 14 15 static inline int myisspace(u8 c) 16 { 17 return c <= ' '; /* Close enough approximation */ 18 } 19 20 /* 21 * Find a non-boolean option, that is, "option=argument". In accordance 22 * with standard Linux practice, if this option is repeated, this returns 23 * the last instance on the command line. 24 * 25 * Returns the length of the argument (regardless of if it was 26 * truncated to fit in the buffer), or -1 on not found. 27 */ 28 int __cmdline_find_option(unsigned long cmdline_ptr, const char *option, char *buffer, int bufsize) 29 { 30 addr_t cptr; 31 char c; 32 int len = -1; 33 const char *opptr = NULL; 34 char *bufptr = buffer; 35 enum { 36 st_wordstart, /* Start of word/after whitespace */ 37 st_wordcmp, /* Comparing this word */ 38 st_wordskip, /* Miscompare, skip */ 39 st_bufcpy /* Copying this to buffer */ 40 } state = st_wordstart; 41 42 if (!cmdline_ptr) 43 return -1; /* No command line */ 44 45 cptr = cmdline_ptr & 0xf; 46 set_fs(cmdline_ptr >> 4); 47 48 while (cptr < 0x10000 && (c = rdfs8(cptr++))) { 49 switch (state) { 50 case st_wordstart: 51 if (myisspace(c)) 52 break; 53 54 /* else */ 55 state = st_wordcmp; 56 opptr = option; 57 fallthrough; 58 59 case st_wordcmp: 60 if (c == '=' && !*opptr) { 61 len = 0; 62 bufptr = buffer; 63 state = st_bufcpy; 64 } else if (myisspace(c)) { 65 state = st_wordstart; 66 } else if (c != *opptr++) { 67 state = st_wordskip; 68 } 69 break; 70 71 case st_wordskip: 72 if (myisspace(c)) 73 state = st_wordstart; 74 break; 75 76 case st_bufcpy: 77 if (myisspace(c)) { 78 state = st_wordstart; 79 } else { 80 if (len < bufsize-1) 81 *bufptr++ = c; 82 len++; 83 } 84 break; 85 } 86 } 87 88 if (bufsize) 89 *bufptr = '\0'; 90 91 return len; 92 } 93 94 /* 95 * Find a boolean option (like quiet,noapic,nosmp....) 96 * 97 * Returns the position of that option (starts counting with 1) 98 * or 0 on not found 99 */ 100 int __cmdline_find_option_bool(unsigned long cmdline_ptr, const char *option) 101 { 102 addr_t cptr; 103 char c; 104 int pos = 0, wstart = 0; 105 const char *opptr = NULL; 106 enum { 107 st_wordstart, /* Start of word/after whitespace */ 108 st_wordcmp, /* Comparing this word */ 109 st_wordskip, /* Miscompare, skip */ 110 } state = st_wordstart; 111 112 if (!cmdline_ptr) 113 return -1; /* No command line */ 114 115 cptr = cmdline_ptr & 0xf; 116 set_fs(cmdline_ptr >> 4); 117 118 while (cptr < 0x10000) { 119 c = rdfs8(cptr++); 120 pos++; 121 122 switch (state) { 123 case st_wordstart: 124 if (!c) 125 return 0; 126 else if (myisspace(c)) 127 break; 128 129 state = st_wordcmp; 130 opptr = option; 131 wstart = pos; 132 fallthrough; 133 134 case st_wordcmp: 135 if (!*opptr) 136 if (!c || myisspace(c)) 137 return wstart; 138 else 139 state = st_wordskip; 140 else if (!c) 141 return 0; 142 else if (c != *opptr++) 143 state = st_wordskip; 144 break; 145 146 case st_wordskip: 147 if (!c) 148 return 0; 149 else if (myisspace(c)) 150 state = st_wordstart; 151 break; 152 } 153 } 154 155 return 0; /* Buffer overrun */ 156 } 157