11 #include <file/file.h>
12 #include <types/types.h>
13 #include <talloc/talloc.h>
19 static struct platform *platform;
20 static struct config *config;
22 static const char *kernel_cmdline_debug = "petitboot.debug";
24 static void dump_config(struct config *config)
28 pb_log("configuration:\n");
30 if (config->autoboot_enabled)
31 pb_log(" autoboot: enabled, %d sec\n",
32 config->autoboot_timeout_sec);
34 pb_log(" autoboot: disabled\n");
36 if (config->network.n_interfaces || config->network.n_dns_servers)
37 pb_log(" network configuration:\n");
39 if (config->safe_mode)
40 pb_log(" safe mode: active\n");
42 if (config->disable_snapshots)
43 pb_log(" dm-snapshots disabled\n");
45 for (i = 0; i < config->network.n_interfaces; i++) {
46 struct interface_config *ifconf =
47 config->network.interfaces[i];
49 pb_log(" interface %02x:%02x:%02x:%02x:%02x:%02x\n",
50 ifconf->hwaddr[0], ifconf->hwaddr[1],
51 ifconf->hwaddr[2], ifconf->hwaddr[3],
52 ifconf->hwaddr[4], ifconf->hwaddr[5]);
59 if (ifconf->method == CONFIG_METHOD_DHCP) {
62 } else if (ifconf->method == CONFIG_METHOD_STATIC) {
64 pb_log(" ip: %s\n", ifconf->static_config.address);
65 pb_log(" gw: %s\n", ifconf->static_config.gateway);
66 pb_log(" url: %s\n", ifconf->static_config.url);
70 for (i = 0; i < config->network.n_dns_servers; i++)
71 pb_log(" dns server %s\n", config->network.dns_servers[i]);
73 for (i = 0; i < config->n_autoboot_opts; i++) {
74 if (config->autoboot_opts[i].boot_type == BOOT_DEVICE_TYPE)
75 pb_log(" boot device %d: %s\n", i,
76 device_type_name(config->autoboot_opts[i].type));
78 pb_log(" boot device %d: uuid: %s\n",
79 i, config->autoboot_opts[i].uuid);
82 pb_log(" IPMI boot device 0x%02x%s\n", config->ipmi_bootdev,
83 config->ipmi_bootdev_persistent ? " (persistent)" : "");
85 pb_log(" Modifications allowed to disks: %s\n",
86 config->allow_writes ? "yes" : "no");
88 pb_log(" Default UI to boot on: %s\n",
89 config->boot_console ?: "none set");
90 if (config->manual_console)
91 pb_log(" (Manually set)\n");
93 if (config->http_proxy)
94 pb_log(" HTTP Proxy: %s\n", config->http_proxy);
95 if (config->https_proxy)
96 pb_log(" HTTPS Proxy: %s\n", config->https_proxy);
99 pb_log(" language: %s\n", config->lang ?: "");
102 static bool config_debug_on_cmdline(void)
107 fd = open("/proc/cmdline", O_RDONLY);
111 rc = read(fd, buf, sizeof(buf));
117 return memmem(buf, rc, kernel_cmdline_debug,
118 strlen(kernel_cmdline_debug)) != NULL;
121 void config_set_defaults(struct config *config)
125 config->autoboot_enabled = true;
126 config->autoboot_timeout_sec = 10;
127 config->autoboot_enabled = true;
128 config->network.interfaces = NULL;
129 config->network.n_interfaces = 0;
130 config->network.dns_servers = NULL;
131 config->network.n_dns_servers = 0;
132 config->http_proxy = NULL;
133 config->https_proxy = NULL;
134 config->safe_mode = false;
135 config->allow_writes = true;
136 config->disable_snapshots = false;
138 config->n_consoles = 0;
139 config->consoles = NULL;
140 config->boot_console = NULL;
142 config->n_autoboot_opts = 2;
143 config->autoboot_opts = talloc_array(config, struct autoboot_option,
144 config->n_autoboot_opts);
145 config->autoboot_opts[0].boot_type = BOOT_DEVICE_TYPE;
146 config->autoboot_opts[0].type = DEVICE_TYPE_NETWORK;
147 config->autoboot_opts[1].boot_type = BOOT_DEVICE_TYPE;
148 config->autoboot_opts[1].type = DEVICE_TYPE_ANY;
150 config->ipmi_bootdev = 0;
151 config->ipmi_bootdev_persistent = false;
153 config->debug = config_debug_on_cmdline();
155 lang = setlocale(LC_ALL, NULL);
156 pb_log_fn("lang: %s\n", lang);
157 if (lang && strlen(lang))
158 config->lang = talloc_strdup(config, lang);
164 int platform_init(void *ctx)
166 extern struct platform *__start_platforms, *__stop_platforms;
169 platform_ctx = talloc_new(ctx);
171 for (p = &__start_platforms; p < &__stop_platforms; p++) {
172 pb_debug("%s: Try platform %s\n", __func__, (*p)->name);
173 if (!(*p)->probe(*p, platform_ctx))
179 config = talloc(platform_ctx, struct config);
180 config_set_defaults(config);
183 pb_log("Detected platform type: %s\n", platform->name);
184 if (platform->load_config)
185 platform->load_config(platform, config);
187 pb_log("No platform type detected, some platform-specific "
188 "functionality will be disabled\n");
196 const struct platform *platform_get(void)
201 void platform_pre_boot(void)
203 const struct config *config = config_get();
205 if (platform && config && platform->pre_boot)
206 platform->pre_boot(platform, config);
209 int platform_get_sysinfo(struct system_info *info)
211 if (platform && platform->get_sysinfo)
212 return platform->get_sysinfo(platform, info);
216 bool platform_restrict_clients(){
217 if (platform && platform->restrict_clients)
218 return platform->restrict_clients(platform);
222 int platform_set_password(const char *hash)
224 if (platform && platform->set_password)
225 return platform->set_password(platform, hash);
229 int config_set(struct config *newconfig)
233 if (!platform || !platform->save_config)
236 if (newconfig == config)
239 pb_log("new configuration data received\n");
240 dump_config(newconfig);
242 rc = platform->save_config(platform, newconfig);
245 config = talloc_steal(platform_ctx, newconfig);
247 pb_log("error saving new configuration; changes lost\n");
252 /* A non-exported function to allow the test infrastructure to initialise
253 * (and change) the configuration variables */
255 struct config __attribute__((unused)) *test_config_init(
256 struct parser_test *test);
257 struct config *test_config_init(struct parser_test *test)
259 config = talloc(test, struct config);
260 config_set_defaults(config);
264 const struct config *config_get(void)
269 void config_set_autoboot(bool autoboot_enabled)
271 config->autoboot_enabled = autoboot_enabled;
273 pb_log("set autoboot: %s\n",
274 config->autoboot_enabled ? "enabled" : "disabled");
277 int platform_fini(void)
279 talloc_free(platform_ctx);
283 static int parse_hwaddr(struct interface_config *ifconf, const char *str)
287 if (strlen(str) != strlen("00:00:00:00:00:00"))
290 for (i = 0; i < HWADDR_SIZE; i++) {
294 byte[0] = str[i * 3 + 0];
295 byte[1] = str[i * 3 + 1];
298 x = strtoul(byte, &endp, 16);
299 if (endp != byte + 2)
302 ifconf->hwaddr[i] = x & 0xff;
308 static int config_parse_one_interface(struct config *config, char *confstr)
310 struct interface_config *ifconf;
311 char *tok, *tok_gw, *tok_url, *saveptr;
313 ifconf = talloc_zero(config, struct interface_config);
315 if (!confstr || !strlen(confstr))
318 /* first token should be the mac address */
319 tok = strtok_r(confstr, ",", &saveptr);
323 if (parse_hwaddr(ifconf, tok))
326 /* second token is the method */
327 tok = strtok_r(NULL, ",", &saveptr);
328 if (!tok || !strlen(tok) || !strcmp(tok, "ignore")) {
329 ifconf->ignore = true;
331 } else if (!strcmp(tok, "dhcp")) {
332 ifconf->method = CONFIG_METHOD_DHCP;
334 } else if (!strcmp(tok, "static")) {
335 ifconf->method = CONFIG_METHOD_STATIC;
337 /* ip/mask, [optional] gateway, [optional] url */
338 tok = strtok_r(NULL, ",", &saveptr);
341 ifconf->static_config.address =
342 talloc_strdup(ifconf, tok);
345 * If a url is set but not a gateway, we can accidentally
346 * interpret the url as the gateway. To avoid changing the
347 * parameter format check if the "gateway" is actually a
348 * pb-url if it's the last token.
350 tok_gw = strtok_r(NULL, ",", &saveptr);
351 tok_url = strtok_r(NULL, ",", &saveptr);
354 if (tok_url || !is_url(tok_gw))
355 ifconf->static_config.gateway =
356 talloc_strdup(ifconf, tok_gw);
362 ifconf->static_config.url =
363 talloc_strdup(ifconf, tok_url);
365 pb_log("Unknown network configuration method %s\n", tok);
369 config->network.interfaces = talloc_realloc(config,
370 config->network.interfaces,
371 struct interface_config *,
372 ++config->network.n_interfaces);
374 config->network.interfaces[config->network.n_interfaces - 1] = ifconf;
382 static int config_parse_one_dns(struct config *config, char *confstr)
384 char *tok, *saveptr = NULL;
386 for (tok = strtok_r(confstr, ",", &saveptr); tok;
387 tok = strtok_r(NULL, ",", &saveptr)) {
389 char *server = talloc_strdup(config, tok);
391 config->network.dns_servers = talloc_realloc(config,
392 config->network.dns_servers, const char *,
393 ++config->network.n_dns_servers);
395 config->network.dns_servers[config->network.n_dns_servers - 1]
402 static void config_populate_network(struct config *config, const char *cval)
404 char *val, *saveptr = NULL;
407 if (!cval || !strlen(cval))
410 val = talloc_strdup(config, cval);
415 tok = strtok_r(i == 0 ? val : NULL, " ", &saveptr);
419 if (!strncasecmp(tok, "dns,", strlen("dns,")))
420 config_parse_one_dns(config, tok + strlen("dns,"));
422 config_parse_one_interface(config, tok);
429 static int read_bootdev(void *ctx, char **pos, struct autoboot_option *opt)
431 char *delim = strchr(*pos, ' ');
432 int len, prefix = 0, rc = -1;
433 enum device_type type;
435 if (!strncmp(*pos, "uuid:", strlen("uuid:"))) {
436 prefix = strlen("uuid:");
437 opt->boot_type = BOOT_DEVICE_UUID;
438 } else if (!strncmp(*pos, "mac:", strlen("mac:"))) {
439 prefix = strlen("mac:");
440 opt->boot_type = BOOT_DEVICE_UUID;
442 type = find_device_type(*pos);
443 if (type != DEVICE_TYPE_UNKNOWN) {
445 opt->boot_type = BOOT_DEVICE_TYPE;
450 if (opt->boot_type == BOOT_DEVICE_UUID) {
452 len = (int)(delim - *pos) - prefix;
454 len = strlen(*pos) - prefix;
457 opt->uuid = talloc_strndup(ctx, *pos + prefix, len);
462 /* Always advance pointer to next option or end */
466 *pos += strlen(*pos);
471 void config_populate_bootdev(struct config *config,
472 const struct param_list *pl)
474 struct autoboot_option *opt, *new = NULL;
476 unsigned int n_new = 0;
479 /* Check for ordered bootdevs */
480 val = param_list_get_value(pl, "petitboot,bootdevs");
481 if (!val || !strlen(val)) {
484 pos = talloc_strdup(config, val);
485 end = strchr(pos, '\0');
488 while (pos && pos < end) {
489 opt = talloc(config, struct autoboot_option);
491 if (read_bootdev(config, &pos, opt)) {
492 pb_log("bootdev config is in an unknown format "
493 "(expected uuid:... or mac:...)\n");
498 new = talloc_realloc(config, new, struct autoboot_option,
507 /* If autoboot has been disabled, clear the default options */
508 if (!config->autoboot_enabled) {
509 talloc_free(config->autoboot_opts);
510 config->n_autoboot_opts = 0;
515 talloc_free(config->autoboot_opts);
516 config->autoboot_opts = new;
517 config->n_autoboot_opts = n_new;
520 void config_populate_all(struct config *config, const struct param_list *pl)
524 unsigned long timeout;
526 /* if the "auto-boot?' property is present and "false", disable auto
528 val = param_list_get_value(pl, "auto-boot?");
529 config->autoboot_enabled = !val || strcmp(val, "false");
531 val = param_list_get_value(pl, "petitboot,timeout");
533 timeout = strtoul(val, &end, 10);
535 if (timeout >= INT_MAX)
537 config->autoboot_timeout_sec = (int)timeout;
541 val = param_list_get_value(pl, "petitboot,language");
542 config->lang = val ? talloc_strdup(config, val) : NULL;
544 val = param_list_get_value(pl, "petitboot,network");
545 config_populate_network(config, val);
547 config_populate_bootdev(config, pl);
549 if (!config->debug) {
550 val = param_list_get_value(pl, "petitboot,debug?");
551 config->debug = val && !strcmp(val, "true");
554 val = param_list_get_value(pl, "petitboot,write?");
556 config->allow_writes = !strcmp(val, "true");
558 val = param_list_get_value(pl, "petitboot,snapshots?");
560 config->disable_snapshots = !strcmp(val, "false");
562 val = param_list_get_value(pl, "petitboot,console");
564 config->boot_console = talloc_strdup(config, val);
565 /* If a full path is already set we don't want to override it */
566 config->manual_console = config->boot_console &&
567 !strchr(config->boot_console, '[');
569 val = param_list_get_value(pl, "petitboot,http_proxy");
571 config->http_proxy = talloc_strdup(config, val);
572 val = param_list_get_value(pl, "petitboot,https_proxy");
574 config->https_proxy = talloc_strdup(config, val);
577 static char *interface_config_str(void *ctx, struct interface_config *config)
581 /* todo: HWADDR size is hardcoded as 6, but we may need to handle
582 * different hardware address formats */
583 str = talloc_asprintf(ctx, "%02x:%02x:%02x:%02x:%02x:%02x,",
584 config->hwaddr[0], config->hwaddr[1],
585 config->hwaddr[2], config->hwaddr[3],
586 config->hwaddr[4], config->hwaddr[5]);
588 if (config->ignore) {
589 str = talloc_asprintf_append(str, "ignore");
591 } else if (config->method == CONFIG_METHOD_DHCP) {
592 str = talloc_asprintf_append(str, "dhcp");
594 } else if (config->method == CONFIG_METHOD_STATIC) {
595 str = talloc_asprintf_append(str, "static,%s%s%s%s%s",
596 config->static_config.address,
597 config->static_config.gateway ? "," : "",
598 config->static_config.gateway ?: "",
599 config->static_config.url ? "," : "",
600 config->static_config.url ?: "");
605 static char *dns_config_str(void *ctx, const char **dns_servers, int n)
610 str = talloc_strdup(ctx, "dns,");
611 for (i = 0; i < n; i++) {
612 str = talloc_asprintf_append(str, "%s%s",
620 void params_update_network_values(struct param_list *pl,
621 const char *param_name, const struct config *config)
627 * Don't store IPMI overrides to NVRAM. If this was a persistent
628 * override it was already stored in NVRAM by
629 * get_ipmi_network_override()
631 if (config->network.n_interfaces &&
632 config->network.interfaces[0]->override)
635 val = talloc_strdup(pl, "");
637 for (i = 0; i < config->network.n_interfaces; i++) {
638 char *iface_str = interface_config_str(pl,
639 config->network.interfaces[i]);
640 val = talloc_asprintf_append(val, "%s%s",
641 *val == '\0' ? "" : " ", iface_str);
642 talloc_free(iface_str);
645 if (config->network.n_dns_servers) {
646 char *dns_str = dns_config_str(pl,
647 config->network.dns_servers,
648 config->network.n_dns_servers);
649 val = talloc_asprintf_append(val, "%s%s",
650 *val == '\0' ? "" : " ", dns_str);
651 talloc_free(dns_str);
654 param_list_set_non_empty(pl, param_name, val, true);
659 void params_update_bootdev_values(struct param_list *pl,
660 const char *param_name, const struct config *config)
662 char *val = NULL, *boot_str = NULL, *tmp = NULL;
663 struct autoboot_option *opt;
664 const char delim = ' ';
667 if (!config->n_autoboot_opts)
670 for (i = 0; i < config->n_autoboot_opts; i++) {
671 opt = &config->autoboot_opts[i];
672 switch (opt->boot_type) {
673 case BOOT_DEVICE_TYPE:
674 boot_str = talloc_asprintf(config, "%s%c",
675 device_type_name(opt->type),
678 case BOOT_DEVICE_UUID:
679 boot_str = talloc_asprintf(config, "uuid:%s%c",
683 tmp = val = talloc_asprintf_append(val, "%s", boot_str);
686 param_list_set_non_empty(pl, param_name, val, true);
690 talloc_free(boot_str);