X-Git-Url: http://git.ozlabs.org/?p=petitboot;a=blobdiff_plain;f=discover%2Fplatform-powerpc.c;h=02d9a207e707463424bb855fb20823f03bc0acc5;hp=0e3a10b29d0de2247bb7593fb90844365bad42f1;hb=3132110c344c60bbe648b5e1b0473bdec101d111;hpb=11284780b9aa525dd659bd85d6374040630db008 diff --git a/discover/platform-powerpc.c b/discover/platform-powerpc.c index 0e3a10b..02d9a20 100644 --- a/discover/platform-powerpc.c +++ b/discover/platform-powerpc.c @@ -53,21 +53,20 @@ static const char *known_params[] = { "auto-boot?", "petitboot,network", "petitboot,timeout", - "petitboot,bootdev", "petitboot,bootdevs", "petitboot,language", "petitboot,debug?", "petitboot,write?", "petitboot,snapshots?", + "petitboot,console", + "petitboot,http_proxy", + "petitboot,https_proxy", NULL, }; #define to_platform_powerpc(p) \ (struct platform_powerpc *)(p->platform_data) -/* a partition max a max size of 64k * 16bytes = 1M */ -static const int max_partition_size = 64 * 1024 * 16; - static bool param_is_known(const char *param, unsigned int len) { const char *known_param; @@ -411,11 +410,9 @@ static int read_bootdev(void *ctx, char **pos, struct autoboot_option *opt) if (!strncmp(*pos, "uuid:", strlen("uuid:"))) { prefix = strlen("uuid:"); opt->boot_type = BOOT_DEVICE_UUID; - rc = 0; } else if (!strncmp(*pos, "mac:", strlen("mac:"))) { prefix = strlen("mac:"); opt->boot_type = BOOT_DEVICE_UUID; - rc = 0; } else { type = find_device_type(*pos); if (type != DEVICE_TYPE_UNKNOWN) { @@ -429,9 +426,12 @@ static int read_bootdev(void *ctx, char **pos, struct autoboot_option *opt) if (delim) len = (int)(delim - *pos) - prefix; else - len = strlen(*pos); + len = strlen(*pos) - prefix; - opt->uuid = talloc_strndup(ctx, *pos + prefix, len); + if (len) { + opt->uuid = talloc_strndup(ctx, *pos + prefix, len); + rc = 0; + } } /* Always advance pointer to next option or end */ @@ -447,22 +447,9 @@ static void populate_bootdev_config(struct platform_powerpc *platform, struct config *config) { struct autoboot_option *opt, *new = NULL; - char *pos, *end, *old_dev = NULL; + char *pos, *end; unsigned int n_new = 0; const char *val; - bool conflict; - - /* Check for old-style bootdev */ - val = get_param(platform, "petitboot,bootdev"); - if (val && strlen(val)) { - pos = talloc_strdup(config, val); - if (!strncmp(val, "uuid:", strlen("uuid:"))) - old_dev = talloc_strdup(config, - val + strlen("uuid:")); - else if (!strncmp(val, "mac:", strlen("mac:"))) - old_dev = talloc_strdup(config, - val + strlen("mac:")); - } /* Check for ordered bootdevs */ val = get_param(platform, "petitboot,bootdevs"); @@ -491,7 +478,7 @@ static void populate_bootdev_config(struct platform_powerpc *platform, } - if (!n_new && !old_dev) { + if (!n_new) { /* If autoboot has been disabled, clear the default options */ if (!config->autoboot_enabled) { talloc_free(config->autoboot_opts); @@ -500,28 +487,9 @@ static void populate_bootdev_config(struct platform_powerpc *platform, return; } - conflict = old_dev && (!n_new || - new[0].boot_type == BOOT_DEVICE_TYPE || - /* Canonical UUIDs are 36 characters long */ - strncmp(new[0].uuid, old_dev, 36)); - - if (!conflict) { - talloc_free(config->autoboot_opts); - config->autoboot_opts = new; - config->n_autoboot_opts = n_new; - return; - } - - /* - * Difference detected, defer to old format in case it has been updated - * recently - */ - pb_debug("Old autoboot bootdev detected\n"); talloc_free(config->autoboot_opts); - config->autoboot_opts = talloc(config, struct autoboot_option); - config->autoboot_opts[0].boot_type = BOOT_DEVICE_UUID; - config->autoboot_opts[0].uuid = talloc_strdup(config, old_dev); - config->n_autoboot_opts = 1; + config->autoboot_opts = new; + config->n_autoboot_opts = n_new; } static void populate_config(struct platform_powerpc *platform, @@ -565,6 +533,20 @@ static void populate_config(struct platform_powerpc *platform, val = get_param(platform, "petitboot,snapshots?"); if (val) config->disable_snapshots = !strcmp(val, "false"); + + val = get_param(platform, "petitboot,console"); + if (val) + config->boot_console = talloc_strdup(config, val); + /* If a full path is already set we don't want to override it */ + config->manual_console = config->boot_console && + !strchr(config->boot_console, '['); + + val = get_param(platform, "petitboot,http_proxy"); + if (val) + config->http_proxy = talloc_strdup(config, val); + val = get_param(platform, "petitboot,https_proxy"); + if (val) + config->https_proxy = talloc_strdup(config, val); } static char *iface_config_str(void *ctx, struct interface_config *config) @@ -630,6 +612,15 @@ static void update_network_config(struct platform_powerpc *platform, unsigned int i; char *val; + /* + * Don't store IPMI overrides to NVRAM. If this was a persistent + * override it was already stored in NVRAM by + * get_ipmi_network_override() + */ + if (config->network.n_interfaces && + config->network.interfaces[0]->override) + return; + val = talloc_strdup(platform, ""); for (i = 0; i < config->network.n_interfaces; i++) { @@ -657,18 +648,13 @@ static void update_network_config(struct platform_powerpc *platform, static void update_bootdev_config(struct platform_powerpc *platform, struct config *config) { - char *val = NULL, *boot_str = NULL, *tmp = NULL, *first = NULL; + char *val = NULL, *boot_str = NULL, *tmp = NULL; struct autoboot_option *opt; const char delim = ' '; unsigned int i; if (!config->n_autoboot_opts) - first = val = ""; - else if (config->autoboot_opts[0].boot_type == BOOT_DEVICE_UUID) - first = talloc_asprintf(config, "uuid:%s", - config->autoboot_opts[0].uuid); - else - first = ""; + val = ""; for (i = 0; i < config->n_autoboot_opts; i++) { opt = &config->autoboot_opts[i]; @@ -687,7 +673,6 @@ static void update_bootdev_config(struct platform_powerpc *platform, } update_string_config(platform, "petitboot,bootdevs", val); - update_string_config(platform, "petitboot,bootdev", first); talloc_free(tmp); if (boot_str) talloc_free(boot_str); @@ -732,6 +717,16 @@ static int update_config(struct platform_powerpc *platform, val = config->allow_writes ? "true" : "false"; update_string_config(platform, "petitboot,write?", val); + if (!config->manual_console) { + val = config->boot_console ?: ""; + update_string_config(platform, "petitboot,console", val); + } + + val = config->http_proxy ?: ""; + update_string_config(platform, "petitboot,http_proxy", val); + val = config->https_proxy ?: ""; + update_string_config(platform, "petitboot,https_proxy", val); + update_network_config(platform, config); update_bootdev_config(platform, config); @@ -745,21 +740,8 @@ static void set_ipmi_bootdev(struct config *config, enum ipmi_bootdev bootdev, config->ipmi_bootdev = bootdev; config->ipmi_bootdev_persistent = persistent; - switch (bootdev) { - case IPMI_BOOTDEV_NONE: - case IPMI_BOOTDEV_DISK: - case IPMI_BOOTDEV_NETWORK: - case IPMI_BOOTDEV_CDROM: - default: - break; - case IPMI_BOOTDEV_SETUP: - config->autoboot_enabled = false; - break; - case IPMI_BOOTDEV_SAFE: - config->autoboot_enabled = false; + if (bootdev == IPMI_BOOTDEV_SAFE) config->safe_mode = true; - break; - } } static int read_bootdev_sysparam(const char *name, uint8_t *val) @@ -956,7 +938,7 @@ static int get_ipmi_bootdev_ipmi(struct platform_powerpc *platform, /* check for valid flags */ if (!(resp[3] & 0x80)) { pb_debug("platform: boot flags are invalid, ignoring\n"); - return 0; + return -1; } *persistent = resp[3] & 0x40; @@ -1036,7 +1018,6 @@ static void get_ipmi_bmc_versions(struct platform *p, struct system_info *info) struct platform_powerpc *platform = p->platform_data; uint16_t resp_len = 16; uint8_t resp[16], bcd; - uint32_t aux_version; int i, rc; /* Retrieve info from current side */ @@ -1054,7 +1035,7 @@ static void get_ipmi_bmc_versions(struct platform *p, struct system_info *info) pb_debug("\n"); } - if (rc == 0 && resp_len == 16) { + if (rc == 0 && (resp_len == 12 || resp_len == 16)) { info->bmc_current = talloc_array(info, char *, 4); info->n_bmc_current = 4; @@ -1064,10 +1045,16 @@ static void get_ipmi_bmc_versions(struct platform *p, struct system_info *info) resp[2]); bcd = resp[4] & 0x0f; bcd += 10 * (resp[4] >> 4); - memcpy(&aux_version, &resp[12], sizeof(aux_version)); + /* rev1.rev2.aux_revision */ info->bmc_current[2] = talloc_asprintf(info, - "Firmware version: %u.%02u.%u", - resp[3], bcd, aux_version); + "Firmware version: %u.%02u", + resp[3], bcd); + if (resp_len == 16) { + info->bmc_current[2] = talloc_asprintf_append( + info->bmc_current[2], + ".%02x%02x%02x%02x", + resp[12], resp[13], resp[14], resp[15]); + } bcd = resp[5] & 0x0f; bcd += 10 * (resp[5] >> 4); info->bmc_current[3] = talloc_asprintf(info, "IPMI version: %u", @@ -1092,7 +1079,7 @@ static void get_ipmi_bmc_versions(struct platform *p, struct system_info *info) pb_debug("\n"); } - if (rc == 0 && resp_len == 16) { + if (rc == 0 && (resp_len == 12 || resp_len == 16)) { info->bmc_golden = talloc_array(info, char *, 4); info->n_bmc_golden = 4; @@ -1102,10 +1089,16 @@ static void get_ipmi_bmc_versions(struct platform *p, struct system_info *info) resp[2]); bcd = resp[4] & 0x0f; bcd += 10 * (resp[4] >> 4); - memcpy(&aux_version, &resp[12], sizeof(aux_version)); + /* rev1.rev2.aux_revision */ info->bmc_golden[2] = talloc_asprintf(info, - "Firmware version: %u.%02u.%u", - resp[3], bcd, aux_version); + "Firmware version: %u.%02u", + resp[3], bcd); + if (resp_len == 16) { + info->bmc_golden[2] = talloc_asprintf_append( + info->bmc_golden[2], + ".%02x%02x%02x%02x", + resp[12], resp[13], resp[14], resp[15]); + } bcd = resp[5] & 0x0f; bcd += 10 * (resp[5] >> 4); info->bmc_golden[3] = talloc_asprintf(info, "IPMI version: %u", @@ -1121,6 +1114,7 @@ static void get_ipmi_network_override(struct platform_powerpc *platform, const uint32_t magic_value = 0x21706221; uint8_t resp[resp_len]; uint32_t cookie; + bool persistent; int i, rc; uint8_t req[] = { 0x61, /* parameter selector: OEM section (network) */ @@ -1169,18 +1163,21 @@ static void get_ipmi_network_override(struct platform_powerpc *platform, return; } - /* Check for valid parameters. For now ignore the persistent flag */ + /* Check that the parameters are valid */ if (resp[2] & 0x80) { pb_debug("platform: network override is invalid/locked\n"); return; } - /* Check for valid parameters in the boot flags section, ignoring the - * persistent bit */ + /* Check for valid parameters in the boot flags section */ if (!(resp[3] & 0x80)) { pb_debug("platform: network override valid flag not set\n"); return; } + /* Read the persistent flag; if it is set we need to save this config */ + persistent = resp[3] & 0x40; + if (persistent) + pb_debug("platform: network override is persistent\n"); /* Check 4-byte cookie value */ i = 4; @@ -1202,7 +1199,48 @@ static void get_ipmi_network_override(struct platform_powerpc *platform, } /* Interpret the rest of the interface config */ - parse_ipmi_interface_override(config, &resp[i], resp_len - i); + rc = parse_ipmi_interface_override(config, &resp[i], resp_len - i); + + if (!rc && persistent) { + /* Write this new config to NVRAM */ + update_network_config(platform, config); + rc = write_nvram(platform); + if (rc) + pb_log("platform: Failed to save persistent interface override\n"); + } +} + +static void get_active_consoles(struct config *config) +{ + struct stat sbuf; + char *fsp_prop = NULL; + + config->n_consoles = 2; + config->consoles = talloc_array(config, char *, config->n_consoles); + if (!config->consoles) + goto err; + + config->consoles[0] = talloc_asprintf(config->consoles, + "/dev/hvc0 [IPMI / Serial]"); + config->consoles[1] = talloc_asprintf(config->consoles, + "/dev/tty1 [VGA]"); + + fsp_prop = talloc_asprintf(config, "%sfsps", devtree_dir); + if (stat(fsp_prop, &sbuf) == 0) { + /* FSP based machines also have a separate serial console */ + config->consoles = talloc_realloc(config, config->consoles, + char *, config->n_consoles + 1); + if (!config->consoles) + goto err; + config->consoles[config->n_consoles++] = talloc_asprintf( + config->consoles, + "/dev/hvc1 [Serial]"); + } + + return; +err: + config->n_consoles = 0; + pb_log("Failed to allocate memory for consoles\n"); } static int load_config(struct platform *p, struct config *config) @@ -1212,13 +1250,13 @@ static int load_config(struct platform *p, struct config *config) rc = parse_nvram(platform); if (rc) - return rc; + pb_log("%s: Failed to parse nvram\n", __func__); populate_config(platform, config); if (platform->get_ipmi_bootdev) { bool bootdev_persistent; - uint8_t bootdev; + uint8_t bootdev = IPMI_BOOTDEV_INVALID; rc = platform->get_ipmi_bootdev(platform, &bootdev, &bootdev_persistent); if (!rc && ipmi_bootdev_is_valid(bootdev)) { @@ -1229,6 +1267,8 @@ static int load_config(struct platform *p, struct config *config) if (platform->ipmi) get_ipmi_network_override(platform, config); + get_active_consoles(config); + return 0; } @@ -1293,6 +1333,7 @@ static bool probe(struct platform *p, void *ctx) { struct platform_powerpc *platform; struct stat statbuf; + bool bmc_present; int rc; /* we need a device tree */ @@ -1308,7 +1349,9 @@ static bool probe(struct platform *p, void *ctx) p->platform_data = platform; - if (ipmi_present()) { + bmc_present = stat("/proc/device-tree/bmc", &statbuf) == 0; + + if (ipmi_present() && bmc_present) { pb_debug("platform: using direct IPMI for IPMI paramters\n"); platform->ipmi = ipmi_open(platform); platform->get_ipmi_bootdev = get_ipmi_bootdev_ipmi; @@ -1323,8 +1366,7 @@ static bool probe(struct platform *p, void *ctx) pb_log("platform: no IPMI parameter support\n"); } - rc = stat("/proc/device-tree/bmc", &statbuf); - if (!rc) + if (bmc_present) platform->get_platform_versions = hostboot_load_versions; return true;