blob: 121425fe9908780f367b5d93e422a1454385f1f5 [file] [log] [blame]
Jeremy Kerr9326d772016-03-17 17:15:02 +08001/**
2 * Copyright © 2016 IBM Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Jeremy Kerrd66195c2016-03-16 17:24:51 +080016
Kun Yi6424cc32018-06-14 14:09:28 -070017#include <ctype.h>
Jeremy Kerrd66195c2016-03-16 17:24:51 +080018#include <err.h>
Andrew Jefferyd30d7572023-04-18 14:51:51 +093019#include <errno.h>
Jeremy Kerrd66195c2016-03-16 17:24:51 +080020#include <fcntl.h>
Kun Yi6424cc32018-06-14 14:09:28 -070021#include <limits.h>
Jeremy Kerrd66195c2016-03-16 17:24:51 +080022#include <stdint.h>
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <strings.h>
Benjamin Fairfcbdea92018-06-04 14:19:25 -070027#include <termios.h> /* for speed_t */
Jeremy Kerrd66195c2016-03-16 17:24:51 +080028#include <unistd.h>
29
30#include <sys/mman.h>
31#include <sys/stat.h>
Alexander Hansen1e04f442024-06-12 16:35:58 +020032
33#include <iniparser/iniparser.h>
34
35#include "config.h"
36#include "config-internal.h"
37
38#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
Jeremy Kerrd66195c2016-03-16 17:24:51 +080039
Jeremy Kerre440a402016-03-17 16:34:14 +080040static const char *config_default_filename = SYSCONFDIR "/obmc-console.conf";
Jeremy Kerrd66195c2016-03-16 17:24:51 +080041
Jeremy Kerrd66195c2016-03-16 17:24:51 +080042const char *config_get_value(struct config *config, const char *name)
43{
Alexander Hansen1e04f442024-06-12 16:35:58 +020044 int rc;
45 char buf[CONFIG_MAX_KEY_LENGTH];
46 rc = snprintf(buf, CONFIG_MAX_KEY_LENGTH, ":%s", name);
Jeremy Kerrd66195c2016-03-16 17:24:51 +080047
Alexander Hansen1e04f442024-06-12 16:35:58 +020048 if (rc < 0) {
Andrew Jefferyba2af962023-05-02 15:02:56 +093049 return NULL;
50 }
51
Alexander Hansen1e04f442024-06-12 16:35:58 +020052 if ((size_t)rc >= sizeof(buf)) {
53 return NULL;
Andrew Jeffery2834c5b2023-04-19 12:47:09 +093054 }
Jeremy Kerrd66195c2016-03-16 17:24:51 +080055
Alexander Hansen1e04f442024-06-12 16:35:58 +020056 const char *value = iniparser_getstring(config->dict, buf, NULL);
Jeremy Kerrd66195c2016-03-16 17:24:51 +080057
Alexander Hansen1e04f442024-06-12 16:35:58 +020058 if (value && strlen(value) == 0) {
59 return NULL;
Jeremy Kerrd66195c2016-03-16 17:24:51 +080060 }
Jeremy Kerrd66195c2016-03-16 17:24:51 +080061
Alexander Hansen1e04f442024-06-12 16:35:58 +020062 return value;
Jeremy Kerr6c8d7812016-03-17 15:05:45 +080063}
64
65struct config *config_init(const char *filename)
66{
67 struct config *config;
68 int fd;
69
Andrew Jeffery2834c5b2023-04-19 12:47:09 +093070 if (!filename) {
Jeremy Kerr6c8d7812016-03-17 15:05:45 +080071 filename = config_default_filename;
Andrew Jeffery2834c5b2023-04-19 12:47:09 +093072 }
Jeremy Kerr6c8d7812016-03-17 15:05:45 +080073
74 fd = open(filename, O_RDONLY);
75 if (fd < 0) {
76 warn("Can't open configuration file %s", filename);
77 return NULL;
78 }
Jeremy Kerr6c8d7812016-03-17 15:05:45 +080079 close(fd);
Jeremy Kerrd66195c2016-03-16 17:24:51 +080080
Alexander Hansen1e04f442024-06-12 16:35:58 +020081 dictionary *dict = iniparser_load(filename);
82
83 if (dict == NULL) {
84 return NULL;
85 }
86
87 config = malloc(sizeof(*config));
88 if (config) {
89 config->dict = dict;
90 }
91
Jeremy Kerrd66195c2016-03-16 17:24:51 +080092 return config;
Jeremy Kerrd66195c2016-03-16 17:24:51 +080093}
94
95void config_fini(struct config *config)
96{
Andrew Jefferyba2af962023-05-02 15:02:56 +093097 if (!config) {
98 return;
99 }
100
Alexander Hansen1e04f442024-06-12 16:35:58 +0200101 if (config->dict) {
102 iniparser_freedict(config->dict);
Jeremy Kerrd66195c2016-03-16 17:24:51 +0800103 }
104
105 free(config);
106}
Jeremy Kerr6c8d7812016-03-17 15:05:45 +0800107
Benjamin Fairfcbdea92018-06-04 14:19:25 -0700108struct terminal_speed_name {
Andrew Jefferya72711a2023-04-18 18:19:41 +0930109 speed_t speed;
110 uint32_t baud;
111 const char *name;
Benjamin Fairfcbdea92018-06-04 14:19:25 -0700112};
113
Andrew Jefferya72711a2023-04-18 18:19:41 +0930114#define TERM_SPEED(x) \
115 { \
116 B##x, x, #x \
117 }
Cheng C Yangf9c8f6c2019-03-04 18:39:52 +0800118
Andrew Jefferya72711a2023-04-18 18:19:41 +0930119// clang-format off
Cheng C Yangf9c8f6c2019-03-04 18:39:52 +0800120static const struct terminal_speed_name terminal_speeds[] = {
121 TERM_SPEED(50),
122 TERM_SPEED(75),
123 TERM_SPEED(110),
124 TERM_SPEED(134),
125 TERM_SPEED(150),
126 TERM_SPEED(200),
127 TERM_SPEED(300),
128 TERM_SPEED(600),
129 TERM_SPEED(1200),
130 TERM_SPEED(1800),
131 TERM_SPEED(2400),
132 TERM_SPEED(4800),
133 TERM_SPEED(9600),
134 TERM_SPEED(19200),
135 TERM_SPEED(38400),
136 TERM_SPEED(57600),
137 TERM_SPEED(115200),
138 TERM_SPEED(230400),
139 TERM_SPEED(460800),
140 TERM_SPEED(500000),
141 TERM_SPEED(576000),
142 TERM_SPEED(921600),
143 TERM_SPEED(1000000),
144 TERM_SPEED(1152000),
145 TERM_SPEED(1500000),
146 TERM_SPEED(2000000),
147 TERM_SPEED(2500000),
148 TERM_SPEED(3000000),
149 TERM_SPEED(3500000),
150 TERM_SPEED(4000000),
151};
Andrew Jefferya72711a2023-04-18 18:19:41 +0930152// clang-format on
Cheng C Yangf9c8f6c2019-03-04 18:39:52 +0800153
154int config_parse_baud(speed_t *speed, const char *baud_string)
155{
Benjamin Fairfcbdea92018-06-04 14:19:25 -0700156 size_t i;
157
Cheng C Yangf9c8f6c2019-03-04 18:39:52 +0800158 for (i = 0; i < ARRAY_SIZE(terminal_speeds); i++) {
Benjamin Fairfcbdea92018-06-04 14:19:25 -0700159 if (strcmp(baud_string, terminal_speeds[i].name) == 0) {
160 *speed = terminal_speeds[i].speed;
161 return 0;
162 }
163 }
164 return -1;
165}
166
Cheng C Yangf9c8f6c2019-03-04 18:39:52 +0800167uint32_t parse_baud_to_int(speed_t speed)
168{
169 size_t i;
170
171 for (i = 0; i < ARRAY_SIZE(terminal_speeds); i++) {
172 if (terminal_speeds[i].speed == speed) {
173 return terminal_speeds[i].baud;
174 }
175 }
176 return 0;
177}
178
179speed_t parse_int_to_baud(uint32_t baud)
180{
181 size_t i;
182
183 for (i = 0; i < ARRAY_SIZE(terminal_speeds); i++) {
184 if (terminal_speeds[i].baud == baud) {
185 return terminal_speeds[i].speed;
186 }
187 }
188 return 0;
189}
190
Medicine Yehd6e8b642024-03-18 01:49:17 -0700191int config_parse_bytesize(const char *size_str, size_t *size)
Kun Yi6424cc32018-06-14 14:09:28 -0700192{
193 struct size_suffix_shift {
194 /* Left shiftwidth corresponding to the suffix. */
Andrew Jefferya72711a2023-04-18 18:19:41 +0930195 size_t shiftwidth;
196 int unit;
Kun Yi6424cc32018-06-14 14:09:28 -0700197 };
198
199 const struct size_suffix_shift suffixes[] = {
200 { 10, 'k' },
201 { 20, 'M' },
202 { 30, 'G' },
203 };
Andrew Jefferya72711a2023-04-18 18:19:41 +0930204 const size_t num_suffixes =
205 sizeof(suffixes) / sizeof(struct size_suffix_shift);
Kun Yi6424cc32018-06-14 14:09:28 -0700206 size_t logsize;
207 char *suffix;
208 size_t i;
209
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930210 if (!size_str) {
Kun Yi6424cc32018-06-14 14:09:28 -0700211 return -1;
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930212 }
Kun Yi6424cc32018-06-14 14:09:28 -0700213
214 logsize = strtoul(size_str, &suffix, 0);
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930215 if (logsize == 0 || logsize >= UINT32_MAX || suffix == size_str) {
Kun Yi6424cc32018-06-14 14:09:28 -0700216 return -1;
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930217 }
Kun Yi6424cc32018-06-14 14:09:28 -0700218
219 /* Ignore spaces between number and suffix */
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930220 while (*suffix && isspace(*suffix)) {
Kun Yi6424cc32018-06-14 14:09:28 -0700221 suffix++;
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930222 }
Kun Yi6424cc32018-06-14 14:09:28 -0700223
224 for (i = 0; i < num_suffixes; i++) {
225 if (*suffix == suffixes[i].unit) {
226 /*
227 * If logsize overflows, probably something was wrong.
228 * Return instead of clamping to an arbitrary value.
229 */
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930230 if (logsize > (UINT32_MAX >> suffixes[i].shiftwidth)) {
Kun Yi6424cc32018-06-14 14:09:28 -0700231 return -1;
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930232 }
Kun Yi6424cc32018-06-14 14:09:28 -0700233
234 logsize <<= suffixes[i].shiftwidth;
235 suffix++;
236 break;
237 }
238 }
239
240 /* Allow suffix like 'kB' */
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930241 while (*suffix && (tolower(*suffix) == 'b' || isspace(*suffix))) {
Kun Yi6424cc32018-06-14 14:09:28 -0700242 suffix++;
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930243 }
Kun Yi6424cc32018-06-14 14:09:28 -0700244
245 if (*suffix) {
246 warn("Invalid suffix!");
247 return -1;
248 }
249
250 *size = logsize;
251 return 0;
252}
253
Ninad Palsule5ba20b52023-05-12 14:03:15 -0500254/* Default console id if not specified on command line or in config */
255#define DEFAULT_CONSOLE_ID "default"
256
257/* Get the console id */
258const char *config_resolve_console_id(struct config *config, const char *id_arg)
259{
260 const char *configured;
261
262 if (id_arg) {
263 return id_arg;
264 }
265
266 if ((configured = config_get_value(config, "console-id"))) {
267 return configured;
268 }
269
Ninad Palsule5ba20b52023-05-12 14:03:15 -0500270 return DEFAULT_CONSOLE_ID;
271}