8 #include <talloc/talloc.h>
11 #include <process/process.h>
15 static const char *partition = "common";
21 struct list_item list;
24 struct platform_powerpc {
28 static const char *known_params[] = {
35 #define to_platform_powerpc(p) \
36 (struct platform_powerpc *)(p->platform_data)
38 /* a partition max a max size of 64k * 16bytes = 1M */
39 static const int max_partition_size = 64 * 1024 * 16;
41 static bool param_is_known(const char *param, unsigned int len)
43 const char *known_param;
46 for (i = 0; known_params[i]; i++) {
47 known_param = known_params[i];
48 if (len == strlen(known_param) &&
49 !strncmp(param, known_param, len))
56 static int parse_nvram_params(struct platform_powerpc *platform,
59 char *pos, *name, *value;
60 unsigned int paramlen;
63 /* discard 2 header lines:
70 for (i = 0; i < len; i++) {
78 fprintf(stderr, "failure parsing nvram output\n");
82 for (pos = buf + i; pos < buf + len; pos += paramlen + 1) {
87 newline = strchr(pos, '\n');
93 paramlen = strlen(pos);
96 value = strchr(pos, '=');
100 namelen = value - name;
104 if (!param_is_known(name, namelen))
109 param = talloc(platform, struct param);
110 param->modified = false;
111 param->name = talloc_strndup(platform, name, namelen);
112 param->value = talloc_strdup(platform, value);
113 list_add(&platform->params, ¶m->list);
119 static int parse_nvram(struct platform_powerpc *platform)
121 struct process *process;
126 argv[1] = "--print-config";
127 argv[2] = "--partition";
131 process = process_create(platform);
132 process->path = "nvram";
133 process->argv = argv;
134 process->keep_stdout = true;
136 rc = process_run_sync(process);
138 if (rc || !process_exit_ok(process)) {
139 fprintf(stderr, "nvram process returned "
140 "non-zero exit status\n");
143 rc = parse_nvram_params(platform, process->stdout_buf,
144 process->stdout_len);
147 process_release(process);
151 static int write_nvram(struct platform_powerpc *platform)
153 struct process *process;
159 argv[1] = "--update-config";
161 argv[3] = "--partition";
165 process = process_create(platform);
166 process->path = "nvram";
167 process->argv = argv;
169 list_for_each_entry(&platform->params, param, list) {
172 if (!param->modified)
175 paramstr = talloc_asprintf(platform, "%s=%s",
176 param->name, param->value);
179 rc = process_run_sync(process);
181 talloc_free(paramstr);
183 if (rc || !process_exit_ok(process)) {
185 pb_log("nvram update process returned "
186 "non-zero exit status\n");
191 process_release(process);
195 static const char *get_param(struct platform_powerpc *platform,
200 list_for_each_entry(&platform->params, param, list)
201 if (!strcmp(param->name, name))
206 static void set_param(struct platform_powerpc *platform, const char *name,
211 list_for_each_entry(&platform->params, param, list) {
212 if (strcmp(param->name, name))
215 if (!strcmp(param->value, value))
218 talloc_free(param->value);
219 param->value = talloc_strdup(param, value);
220 param->modified = true;
225 param = talloc(platform, struct param);
226 param->modified = true;
227 param->name = talloc_strdup(platform, name);
228 param->value = talloc_strdup(platform, value);
229 list_add(&platform->params, ¶m->list);
232 static int parse_hwaddr(struct interface_config *ifconf, char *str)
236 if (strlen(str) != strlen("00:00:00:00:00:00"))
239 for (i = 0; i < HWADDR_SIZE; i++) {
243 byte[0] = str[i * 3 + 0];
244 byte[1] = str[i * 3 + 1];
247 x = strtoul(byte, &endp, 16);
248 if (endp != byte + 2)
251 ifconf->hwaddr[i] = x & 0xff;
257 static int parse_one_interface_config(struct config *config,
260 struct interface_config *ifconf;
263 ifconf = talloc_zero(config, struct interface_config);
265 if (!confstr || !strlen(confstr))
268 /* first token should be the mac address */
269 tok = strtok_r(confstr, ",", &saveptr);
273 if (parse_hwaddr(ifconf, tok))
276 /* second token is the method */
277 tok = strtok_r(NULL, ",", &saveptr);
278 if (!tok || !strlen(tok) || !strcmp(tok, "ignore")) {
279 ifconf->ignore = true;
281 } else if (!strcmp(tok, "dhcp")) {
282 ifconf->method = CONFIG_METHOD_DHCP;
284 } else if (!strcmp(tok, "static")) {
285 ifconf->method = CONFIG_METHOD_STATIC;
287 /* ip/mask, [optional] gateway */
288 tok = strtok_r(NULL, ",", &saveptr);
291 ifconf->static_config.address =
292 talloc_strdup(ifconf, tok);
294 tok = strtok_r(NULL, ",", &saveptr);
296 ifconf->static_config.gateway =
297 talloc_strdup(ifconf, tok);
301 pb_log("Unknown network configuration method %s\n", tok);
305 config->network.interfaces = talloc_realloc(config,
306 config->network.interfaces,
307 struct interface_config *,
308 ++config->network.n_interfaces);
310 config->network.interfaces[config->network.n_interfaces - 1] = ifconf;
318 static int parse_one_dns_config(struct config *config,
323 for (tok = strtok_r(confstr, ",", &saveptr); tok;
324 tok = strtok_r(NULL, ",", &saveptr)) {
326 char *server = talloc_strdup(config, tok);
328 config->network.dns_servers = talloc_realloc(config,
329 config->network.dns_servers, const char *,
330 ++config->network.n_dns_servers);
332 config->network.dns_servers[config->network.n_dns_servers - 1]
339 static void populate_network_config(struct platform_powerpc *platform,
340 struct config *config)
346 cval = get_param(platform, "petitboot,network");
347 if (!cval || !strlen(cval))
350 val = talloc_strdup(config, cval);
355 tok = strtok_r(i == 0 ? val : NULL, " ", &saveptr);
359 if (!strncasecmp(tok, "dns,", strlen("dns,")))
360 parse_one_dns_config(config, tok + strlen("dns,"));
362 parse_one_interface_config(config, tok);
369 static void populate_config(struct platform_powerpc *platform,
370 struct config *config)
374 unsigned long timeout;
376 /* if the "auto-boot?' property is present and "false", disable auto
378 val = get_param(platform, "auto-boot?");
379 config->autoboot_enabled = !val || strcmp(val, "false");
381 val = get_param(platform, "petitboot,timeout");
383 timeout = strtoul(val, &end, 10);
385 if (timeout >= INT_MAX)
387 config->autoboot_timeout_sec = (int)timeout;
391 populate_network_config(platform, config);
394 static char *iface_config_str(void *ctx, struct interface_config *config)
398 /* todo: HWADDR size is hardcoded as 6, but we may need to handle
399 * different hardware address formats */
400 str = talloc_asprintf(ctx, "%02x:%02x:%02x:%02x:%02x:%02x,",
401 config->hwaddr[0], config->hwaddr[1],
402 config->hwaddr[2], config->hwaddr[3],
403 config->hwaddr[4], config->hwaddr[5]);
405 if (config->ignore) {
406 str = talloc_asprintf_append(str, "ignore");
408 } else if (config->method == CONFIG_METHOD_DHCP) {
409 str = talloc_asprintf_append(str, "dhcp");
411 } else if (config->method == CONFIG_METHOD_STATIC) {
412 str = talloc_asprintf_append(str, "static,%s%s%s",
413 config->static_config.address,
414 config->static_config.gateway ? "," : "",
415 config->static_config.gateway ?: "");
420 static char *dns_config_str(void *ctx, const char **dns_servers, int n)
425 str = talloc_strdup(ctx, "dns,");
426 for (i = 0; i < n; i++) {
427 str = talloc_asprintf_append(str, "%s%s",
435 static void update_string_config(struct platform_powerpc *platform,
436 const char *name, const char *value)
440 cur = get_param(platform, name);
442 /* don't set an empty parameter if it doesn't already exist */
443 if (!cur && !strlen(value))
446 set_param(platform, name, value);
449 static void update_network_config(struct platform_powerpc *platform,
450 struct config *config)
455 val = talloc_strdup(platform, "");
457 for (i = 0; i < config->network.n_interfaces; i++) {
458 char *iface_str = iface_config_str(platform,
459 config->network.interfaces[i]);
460 val = talloc_asprintf_append(val, "%s%s",
461 *val == '\0' ? "" : " ", iface_str);
462 talloc_free(iface_str);
465 if (config->network.n_dns_servers) {
466 char *dns_str = dns_config_str(platform,
467 config->network.dns_servers,
468 config->network.n_dns_servers);
469 val = talloc_asprintf_append(val, "%s%s",
470 *val == '\0' ? "" : " ", dns_str);
471 talloc_free(dns_str);
474 update_string_config(platform, "petitboot,network", val);
479 static int update_config(struct platform_powerpc *platform,
480 struct config *config, struct config *defaults)
485 if (config->autoboot_enabled == defaults->autoboot_enabled)
488 val = config->autoboot_enabled ? "true" : "false";
489 update_string_config(platform, "auto-boot?", val);
491 if (config->autoboot_timeout_sec == defaults->autoboot_timeout_sec)
494 val = tmp = talloc_asprintf(platform, "%d",
495 config->autoboot_timeout_sec);
497 update_string_config(platform, "petitboot,timeout", val);
501 update_network_config(platform, config);
503 return write_nvram(platform);
506 static int load_config(struct platform *p, struct config *config)
508 struct platform_powerpc *platform = to_platform_powerpc(p);
511 rc = parse_nvram(platform);
515 populate_config(platform, config);
520 static int save_config(struct platform *p, struct config *config)
522 struct platform_powerpc *platform = to_platform_powerpc(p);
523 struct config *defaults;
526 defaults = talloc_zero(platform, struct config);
527 config_set_defaults(defaults);
529 rc = update_config(platform, config, defaults);
531 talloc_free(defaults);
535 static bool probe(struct platform *p, void *ctx)
537 struct platform_powerpc *platform;
539 platform = talloc(ctx, struct platform_powerpc);
540 list_init(&platform->params);
542 p->platform_data = platform;
546 static struct platform platform_powerpc = {
549 .load_config = load_config,
550 .save_config = save_config,
553 register_platform(platform_powerpc);