L4Re Operating System Framework
Interface and Usage Documentation
Loading...
Searching...
No Matches
options.cc
1/*
2 * Copyright (C) 2016-2017, 2019, 2022-2025 Kernkonzept GmbH.
3 * Author(s): Jean Wolter <jean.wolter@kernkonzept.com>
4 * Manuel von Oltersdorff-Kalettka <manuel.kalettka@kernkonzept.de>
5 *
6 * License: see LICENSE.spdx (in this directory or the directories above)
7 */
8
9#include <getopt.h>
10#include <stdlib.h>
11#include <cstring>
12#include <type_traits>
13
14#include <l4/cxx/exceptions>
15#include <l4/re/error_helper>
16#include <l4/re/env>
17
18#include "debug.h"
19#include "options.h"
20
21bool
22parse_int_optstring(char const *optstring, int *out)
23{
24 char *endp;
25
26 errno = 0;
27 long num = strtol(optstring, &endp, 10);
28
29 // check that long can be converted to int
30 if (errno || *endp != '\0' || num < INT_MIN || num > INT_MAX)
31 return false;
32
33 *out = num;
34
35 return true;
36}
37
38static int
39verbosity_mask_from_string(char const *str, unsigned *mask)
40{
41 if (strcmp("quiet", str) == 0)
42 {
43 *mask = Dbg::Quiet;
44 return 0;
45 }
46 if (strcmp("warn", str) == 0)
47 {
48 *mask = Dbg::Warn;
49 return 0;
50 }
51 if (strcmp("info", str) == 0)
52 {
53 *mask = Dbg::Warn | Dbg::Info;
54 return 0;
55 }
56 if (strcmp("debug", str) == 0)
57 {
58 *mask = Dbg::Warn | Dbg::Info | Dbg::Debug;
59 return 0;
60 }
61 if (strcmp("trace", str) == 0)
62 {
63 *mask = Dbg::Warn | Dbg::Info | Dbg::Debug | Dbg::Trace;
64 return 0;
65 }
66
67 return -L4_ENOENT;
68}
69
99static void
100set_verbosity(char const *str)
101{
102 unsigned mask;
103 if (verbosity_mask_from_string(str, &mask) == 0)
104 {
105 Dbg::set_verbosity(mask);
106 return;
107 }
108
109 static char const *const components[] =
110 { "core", "virtio", "port", "request", "queue", "packet" };
111
112 static_assert(std::extent<decltype(components)>::value == Dbg::Max_component,
113 "Component names must match 'enum Component'.");
114
115 for (unsigned i = 0; i < Dbg::Max_component; ++i)
116 {
117 auto len = strlen(components[i]);
118 if (strncmp(components[i], str, len) == 0 && str[len] == '='
119 && verbosity_mask_from_string(str + len + 1, &mask) == 0)
120 {
121 Dbg::set_verbosity(i, mask);
122 return;
123 }
124 }
125}
126
127int
128Options::parse_cmd_line(int argc, char **argv,
129 std::shared_ptr<Ds_vector> trusted_dataspaces)
130{
131 int opt, index;
132
133 struct option options[] =
134 {
135 {"size", 1, 0, 's' }, // size of in/out queue == #buffers in queue
136 {"ports", 1, 0, 'p' }, // number of ports
137 {"mac", 0, 0, 'm' }, // switch sets MAC address for each client
138 {"no-random-mac", 0, 0, 'M' }, // don't assign random MAC address to ports by default
139 {"debug", 1, 0, 'D' }, // configure debug levels
140 {"verbose", 0, 0, 'v' },
141 {"quiet", 0, 0, 'q' },
142 {"register-ds", 1, 0, 'd' }, // register a trusted dataspace
143 {0, 0, 0, 0}
144 };
145
146 unsigned long verbosity = Dbg::Warn;
147
148 Dbg info(Dbg::Core, Dbg::Info);
149
150 Dbg::set_verbosity(Dbg::Core, Dbg::Info);
151 info.printf("Arguments:\n");
152 for (int i = 0; i < argc; ++i)
153 info.printf("\t%s\n", argv[i]);
154
155 Dbg::set_verbosity(verbosity);
156 while ( (opt = getopt_long(argc, argv, "s:p:mMqvD:d:", options, &index)) != -1)
157 {
158 switch (opt)
159 {
160 case 's':
161
162 // QueueNumMax must be power of 2 between 1 and 0x8000
163 if (!parse_int_optstring(optarg, &_virtq_max_num)
164 || _virtq_max_num < 1 || _virtq_max_num > 32768
165 || (_virtq_max_num & (_virtq_max_num - 1)))
166 {
167 Err().printf("Max number of virtqueue buffers must be power of 2"
168 " between 1 and 32768. Invalid value %i or argument "
169 "%s\n",
170 _virtq_max_num, optarg);
171 return -1;
172 }
173 info.printf("Max number of buffers in virtqueue: %i\n",
174 _virtq_max_num);
175 break;
176 case 'p':
177 if (parse_int_optstring(optarg, &_max_ports))
178 info.printf("Max number of ports: %u\n", _max_ports);
179 else
180 {
181 Err().printf("Invalid number of ports argument: %s\n", optarg);
182 return -1;
183 }
184 break;
185 case 'q':
186 verbosity = Dbg::Quiet;
187 Dbg::set_verbosity(verbosity);
188 break;
189 case 'v':
190 verbosity = (verbosity << 1) | 1;
191 Dbg::set_verbosity(verbosity);
192 break;
193 case 'D':
194 set_verbosity(optarg);
195 break;
196 case 'm':
197 info.printf("Option -m ignored to compatibility.\n");
198 break;
199 case 'M':
200 _assign_mac = false;
201 break;
202 case 'd':
203 {
204 L4::Cap<L4Re::Dataspace> ds =
205 L4Re::chkcap(L4Re::Env::env()->get_cap<L4Re::Dataspace>(optarg),
206 "Find a dataspace capability.\n");
207 trusted_dataspaces->push_back(ds);
208 break;
209 }
210 default:
211 Err().printf("Unknown command line option '%c' (%d)\n", opt, opt);
212 return -1;
213 }
214 }
215 return 0;
216}
217
218static Options options;
219
220Options const *
221Options::get_options()
222{ return &options; }
223
224Options const *
225Options::parse_options(int argc, char **argv,
226 std::shared_ptr<Ds_vector> trusted_dataspaces)
227{
228 if (options.parse_cmd_line(argc, argv, trusted_dataspaces) < 0)
229 return nullptr;
230
231 return &options;
232}
static Env const * env() noexcept
Returns the initial environment for the current task.
Definition env:96
Environment interface.
Error helper.
Base exceptions.
getopt
@ L4_ENOENT
No such entity.
Definition err.h:35
T chkcap(T &&cap, char const *extra="", l4_ret_t err=-L4_ENOMEM)
Check for valid capability or raise C++ exception.
Definition error_helper:149