X-Git-Url: http://git.ozlabs.org/?p=petitboot;a=blobdiff_plain;f=lib%2Fpb-config%2Fstorage-powerpc-nvram.c;h=e3719761606f1010e244a7b7e89b44b21d725558;hp=fa2437c586a289408c829fbaea6ce730a735eb3c;hb=dea7842fb28ff055b4e0f43a6a1fdaf3c4b5ba89;hpb=e17f6c7e1bcf7a5f67d0f1a51c39af0d8ab104d4 diff --git a/lib/pb-config/storage-powerpc-nvram.c b/lib/pb-config/storage-powerpc-nvram.c index fa2437c..e371976 100644 --- a/lib/pb-config/storage-powerpc-nvram.c +++ b/lib/pb-config/storage-powerpc-nvram.c @@ -137,8 +137,7 @@ static int parse_nvram(struct powerpc_nvram_storage *nv) rc = process_run_sync(process); - if (rc || !WIFEXITED(process->exit_status) - || WEXITSTATUS(process->exit_status)) { + if (rc || !process_exit_ok(process)) { fprintf(stderr, "nvram process returned " "non-zero exit status\n"); rc = -1; @@ -151,6 +150,50 @@ static int parse_nvram(struct powerpc_nvram_storage *nv) return rc; } +static int write_nvram(struct powerpc_nvram_storage *nv) +{ + struct process *process; + struct param *param; + const char *argv[6]; + int rc; + + argv[0] = "nvram"; + argv[1] = "--update-config"; + argv[2] = NULL; + argv[3] = "--partition"; + argv[4] = partition; + argv[5] = NULL; + + process = process_create(nv); + process->path = "nvram"; + process->argv = argv; + + list_for_each_entry(&nv->params, param, list) { + char *paramstr; + + if (!param->modified) + continue; + + paramstr = talloc_asprintf(nv, "%s=%s", + param->name, param->value); + argv[2] = paramstr; + + rc = process_run_sync(process); + + talloc_free(paramstr); + + if (rc || !process_exit_ok(process)) { + rc = -1; + pb_log("nvram update process returned " + "non-zero exit status\n"); + break; + } + } + + process_release(process); + return rc; +} + static const char *get_param(struct powerpc_nvram_storage *nv, const char *name) { @@ -162,6 +205,32 @@ static const char *get_param(struct powerpc_nvram_storage *nv, return NULL; } +static void set_param(struct powerpc_nvram_storage *nv, const char *name, + const char *value) +{ + struct param *param; + + list_for_each_entry(&nv->params, param, list) { + if (strcmp(param->name, name)) + continue; + + if (!strcmp(param->value, value)) + return; + + talloc_free(param->value); + param->value = talloc_strdup(param, value); + param->modified = true; + return; + } + + + param = talloc(nv, struct param); + param->modified = true; + param->name = talloc_strdup(nv, name); + param->value = talloc_strdup(nv, value); + list_add(&nv->params, ¶m->list); +} + static int parse_hwaddr(struct interface_config *ifconf, char *str) { int i; @@ -193,7 +262,7 @@ static int parse_one_interface_config(struct config *config, struct interface_config *ifconf; char *tok, *saveptr; - ifconf = talloc(config, struct interface_config); + ifconf = talloc_zero(config, struct interface_config); if (!confstr || !strlen(confstr)) goto out_err; @@ -324,6 +393,117 @@ static void populate_config(struct powerpc_nvram_storage *nv, populate_network_config(nv, config); } +static char *iface_config_str(void *ctx, struct interface_config *config) +{ + char *str; + + /* todo: HWADDR size is hardcoded as 6, but we may need to handle + * different hardware address formats */ + str = talloc_asprintf(ctx, "%02x:%02x:%02x:%02x:%02x:%02x,", + config->hwaddr[0], config->hwaddr[1], + config->hwaddr[2], config->hwaddr[3], + config->hwaddr[4], config->hwaddr[5]); + + if (config->ignore) { + str = talloc_asprintf_append(str, "ignore"); + + } else if (config->method == CONFIG_METHOD_DHCP) { + str = talloc_asprintf_append(str, "dhcp"); + + } else if (config->method == CONFIG_METHOD_STATIC) { + str = talloc_asprintf_append(str, "static,%s%s%s", + config->static_config.address, + config->static_config.gateway ? "," : "", + config->static_config.gateway ?: ""); + } + return str; +} + +static char *dns_config_str(void *ctx, const char **dns_servers, int n) +{ + char *str; + int i; + + str = talloc_strdup(ctx, "dns,"); + for (i = 0; i < n; i++) { + str = talloc_asprintf_append(str, "%s%s", + i == 0 ? "" : ",", + dns_servers[i]); + } + + return str; +} + +static void update_string_config(struct powerpc_nvram_storage *nv, + const char *name, const char *value) +{ + const char *cur; + + cur = get_param(nv, name); + + /* don't set an empty parameter if it doesn't already exist */ + if (!cur && !strlen(value)) + return; + + set_param(nv, name, value); +} + +static void update_network_config(struct powerpc_nvram_storage *nv, + struct config *config) +{ + unsigned int i; + char *val; + + val = talloc_strdup(nv, ""); + + for (i = 0; i < config->network.n_interfaces; i++) { + char *iface_str = iface_config_str(nv, + config->network.interfaces[i]); + val = talloc_asprintf_append(val, "%s%s", + *val == '\0' ? "" : " ", iface_str); + talloc_free(iface_str); + } + + if (config->network.n_dns_servers) { + char *dns_str = dns_config_str(nv, config->network.dns_servers, + config->network.n_dns_servers); + val = talloc_asprintf_append(val, "%s%s", + *val == '\0' ? "" : " ", dns_str); + talloc_free(dns_str); + } + + update_string_config(nv, "petitboot,network", val); + + talloc_free(val); +} + +static int update_config(struct powerpc_nvram_storage *nv, + struct config *config, struct config *defaults) +{ + char *tmp = NULL; + const char *val; + + if (config->autoboot_enabled == defaults->autoboot_enabled) + val = ""; + else + val = config->autoboot_enabled ? "true" : "false"; + update_string_config(nv, "auto-boot?", val); + + if (config->autoboot_timeout_sec == defaults->autoboot_timeout_sec) + val = ""; + else + val = tmp = talloc_asprintf(nv, "%d", + config->autoboot_timeout_sec); + + update_string_config(nv, "petitboot,timeout", val); + if (tmp) + talloc_free(tmp); + + update_network_config(nv, config); + + return write_nvram(nv); +} + static int load(struct config_storage *st, struct config *config) { struct powerpc_nvram_storage *nv = to_powerpc_nvram_storage(st); @@ -338,12 +518,28 @@ static int load(struct config_storage *st, struct config *config) return 0; } +static int save(struct config_storage *st, struct config *config) +{ + struct powerpc_nvram_storage *nv = to_powerpc_nvram_storage(st); + struct config *defaults; + int rc; + + defaults = talloc_zero(nv, struct config); + config_set_defaults(defaults); + + rc = update_config(nv, config, defaults); + + talloc_free(defaults); + return rc; +} + struct config_storage *create_powerpc_nvram_storage(void *ctx) { struct powerpc_nvram_storage *nv; nv = talloc(ctx, struct powerpc_nvram_storage); nv->storage.load = load; + nv->storage.save = save; list_init(&nv->params); return &nv->storage;