1 /* SPDX-License-Identifier: GPL-2.0-only */
2
3 #include "common.h"
4 #include "opts.h"
5
6 nvramtool_op_info_t nvramtool_op;
7
8 nvramtool_op_modifier_info_t nvramtool_op_modifiers[NVRAMTOOL_NUM_OP_MODIFIERS];
9
10 static char *handle_optional_arg(int argc, char *argv[]);
11 static void register_op(int *op_found, nvramtool_op_t op, char op_param[]);
12 static void register_op_modifier(nvramtool_op_modifier_t mod, char mod_param[]);
13 static void resolve_op_modifiers(void);
14 static void sanity_check_args(void);
15
16 static const char getopt_string[] = "-ab:B:c::C:dD:e:hH:iL:l::np:r:tvw:xX:y:Y";
17
18 /****************************************************************************
19 * parse_nvramtool_args
20 *
21 * Parse command line arguments.
22 ****************************************************************************/
parse_nvramtool_args(int argc,char * argv[])23 void parse_nvramtool_args(int argc, char *argv[])
24 {
25 nvramtool_op_modifier_info_t *mod_info;
26 int i, op_found, c;
27
28 for (i = 0, mod_info = nvramtool_op_modifiers;
29 i < NVRAMTOOL_NUM_OP_MODIFIERS; i++, mod_info++) {
30 mod_info->found = FALSE;
31 mod_info->found_seq = 0;
32 mod_info->param = NULL;
33 }
34
35 op_found = FALSE;
36 opterr = 0;
37
38 do {
39 switch (c = getopt(argc, argv, getopt_string)) {
40 case 'a':
41 register_op(&op_found,
42 NVRAMTOOL_OP_CMOS_SHOW_ALL_PARAMS, NULL);
43 break;
44 case 'b':
45 register_op(&op_found, NVRAMTOOL_OP_WRITE_CMOS_DUMP,
46 optarg);
47 break;
48 case 'B':
49 register_op(&op_found, NVRAMTOOL_OP_READ_CMOS_DUMP,
50 optarg);
51 break;
52 case 'c':
53 register_op(&op_found, NVRAMTOOL_OP_CMOS_CHECKSUM,
54 handle_optional_arg(argc, argv));
55 break;
56 case 'C':
57 register_op_modifier(NVRAMTOOL_MOD_USE_CBFS_FILE,
58 optarg);
59 break;
60 case 'd':
61 register_op(&op_found, NVRAMTOOL_OP_LBTABLE_DUMP, NULL);
62 break;
63 case 'D':
64 register_op_modifier(NVRAMTOOL_MOD_USE_CMOS_FILE,
65 optarg);
66 break;
67 case 'e':
68 register_op(&op_found, NVRAMTOOL_OP_SHOW_PARAM_VALUES,
69 optarg);
70 break;
71 case 'h':
72 register_op(&op_found, NVRAMTOOL_OP_SHOW_USAGE, NULL);
73 break;
74 case 'H':
75 register_op(&op_found, NVRAMTOOL_OP_WRITE_HEADER_FILE, optarg);
76 break;
77 case 'i':
78 register_op(&op_found,
79 NVRAMTOOL_OP_CMOS_SET_PARAMS_STDIN, NULL);
80 break;
81 case 'l':
82 register_op(&op_found, NVRAMTOOL_OP_LBTABLE_SHOW_INFO,
83 handle_optional_arg(argc, argv));
84 break;
85 case 'L':
86 register_op(&op_found, NVRAMTOOL_OP_WRITE_BINARY_FILE,
87 optarg);
88 break;
89 case 'n':
90 register_op_modifier(NVRAMTOOL_MOD_SHOW_VALUE_ONLY,
91 NULL);
92 break;
93 case 'p':
94 register_op(&op_found,
95 NVRAMTOOL_OP_CMOS_SET_PARAMS_FILE, optarg);
96 break;
97 case 'r':
98 register_op(&op_found, NVRAMTOOL_OP_CMOS_SHOW_ONE_PARAM,
99 optarg);
100 break;
101 case 't':
102 register_op_modifier(NVRAMTOOL_MOD_USE_CMOS_OPT_TABLE,
103 NULL);
104 break;
105 case 'v':
106 register_op(&op_found, NVRAMTOOL_OP_SHOW_VERSION, NULL);
107 break;
108 case 'w':
109 register_op(&op_found, NVRAMTOOL_OP_CMOS_SET_ONE_PARAM,
110 optarg);
111 break;
112 case 'x':
113 register_op(&op_found, NVRAMTOOL_OP_SHOW_CMOS_HEX_DUMP,
114 NULL);
115 break;
116 case 'X':
117 register_op(&op_found, NVRAMTOOL_OP_SHOW_CMOS_DUMPFILE,
118 optarg);
119 break;
120 case 'y':
121 register_op_modifier(NVRAMTOOL_MOD_USE_CMOS_LAYOUT_FILE,
122 optarg);
123 break;
124 case 'Y':
125 register_op(&op_found, NVRAMTOOL_OP_SHOW_LAYOUT, NULL);
126 break;
127 case -1: /* no more command line args */
128 break;
129 case '?': /* unknown option found */
130 case 1: /* nonoption command line arg found */
131 default:
132 usage(stderr);
133 break;
134 }
135 } while (c != -1);
136
137 if (!op_found)
138 usage(stderr);
139
140 resolve_op_modifiers();
141 sanity_check_args();
142 }
143
144 /****************************************************************************
145 * handle_optional_arg
146 *
147 * Handle a command line option with an optional argument.
148 ****************************************************************************/
handle_optional_arg(int argc,char * argv[])149 static char *handle_optional_arg(int argc, char *argv[])
150 {
151 char *arg;
152
153 if (optarg != NULL) {
154 /* optional arg is present and arg was specified as
155 * "-zarg" (with no whitespace between "z" and "arg"),
156 * where -z is the option and "arg" is the value of the
157 * optional arg
158 */
159 return optarg;
160 }
161
162 if ((argv[optind] == NULL) || (argv[optind][0] == '-'))
163 return NULL;
164
165 arg = argv[optind]; /* optional arg is present */
166
167 /* This call to getopt yields the optional arg we just found,
168 * which we want to skip.
169 */
170 getopt(argc, argv, getopt_string);
171
172 return arg;
173 }
174
175 /****************************************************************************
176 * register_op
177 *
178 * Store the user's selection of which operation this program should perform.
179 ****************************************************************************/
register_op(int * op_found,nvramtool_op_t op,char op_param[])180 static void register_op(int *op_found, nvramtool_op_t op, char op_param[])
181 {
182 if (*op_found && (op != nvramtool_op.op))
183 usage(stderr);
184
185 *op_found = TRUE;
186 nvramtool_op.op = op;
187 nvramtool_op.param = op_param;
188 }
189
190 /****************************************************************************
191 * register_op_modifier
192 *
193 * Store information regarding an optional argument specified in addition to
194 * the user's selection of which operation this program should perform.
195 ****************************************************************************/
register_op_modifier(nvramtool_op_modifier_t mod,char mod_param[])196 static void register_op_modifier(nvramtool_op_modifier_t mod, char mod_param[])
197 {
198 static int found_seq = 0;
199 nvramtool_op_modifier_info_t *mod_info;
200
201 mod_info = &nvramtool_op_modifiers[mod];
202 mod_info->found = TRUE;
203 mod_info->found_seq = ++found_seq;
204 mod_info->param = mod_param;
205 }
206
207 /****************************************************************************
208 * resolve_op_modifiers
209 *
210 * If the user specifies multiple arguments that conflict with each other,
211 * the last specified argument overrides previous conflicting arguments.
212 ****************************************************************************/
resolve_op_modifiers(void)213 static void resolve_op_modifiers(void)
214 {
215 if (nvramtool_op_modifiers[NVRAMTOOL_MOD_USE_CMOS_LAYOUT_FILE].found &&
216 nvramtool_op_modifiers[NVRAMTOOL_MOD_USE_CMOS_OPT_TABLE].found) {
217 if (nvramtool_op_modifiers[NVRAMTOOL_MOD_USE_CMOS_LAYOUT_FILE].found_seq >
218 nvramtool_op_modifiers[NVRAMTOOL_MOD_USE_CMOS_OPT_TABLE].found_seq)
219 nvramtool_op_modifiers
220 [NVRAMTOOL_MOD_USE_CMOS_OPT_TABLE].found = FALSE;
221 else
222 nvramtool_op_modifiers
223 [NVRAMTOOL_MOD_USE_CMOS_LAYOUT_FILE].found = FALSE;
224 }
225 }
226
227 /****************************************************************************
228 * sanity_check_args
229 *
230 * Perform sanity checking on command line arguments.
231 ****************************************************************************/
sanity_check_args(void)232 static void sanity_check_args(void)
233 {
234 if ((nvramtool_op_modifiers[NVRAMTOOL_MOD_SHOW_VALUE_ONLY].found) &&
235 (nvramtool_op.op != NVRAMTOOL_OP_CMOS_SHOW_ONE_PARAM))
236 usage(stderr);
237 }
238