Merge tag 'efi_updates_for_v5.11' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6-microblaze.git] / arch / x86 / boot / cmdline.c
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 }