diff options
author | Angelos Mouzakitis <a.mouzakitis@virtualopensystems.com> | 2023-10-10 14:33:42 +0000 |
---|---|---|
committer | Angelos Mouzakitis <a.mouzakitis@virtualopensystems.com> | 2023-10-10 14:33:42 +0000 |
commit | af1a266670d040d2f4083ff309d732d648afba2a (patch) | |
tree | 2fc46203448ddcc6f81546d379abfaeb323575e9 /roms/skiboot/core/flash-firmware-versions.c | |
parent | e02cda008591317b1625707ff8e115a4841aa889 (diff) |
Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec
Diffstat (limited to 'roms/skiboot/core/flash-firmware-versions.c')
-rw-r--r-- | roms/skiboot/core/flash-firmware-versions.c | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/roms/skiboot/core/flash-firmware-versions.c b/roms/skiboot/core/flash-firmware-versions.c new file mode 100644 index 000000000..975ac6aff --- /dev/null +++ b/roms/skiboot/core/flash-firmware-versions.c @@ -0,0 +1,164 @@ +// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later +/* + * Parse VERSION partition, add to device tree + * + * Copyright 2013-2018 IBM Corp. + */ + +#include <skiboot.h> +#include <device.h> +#include <opal.h> +#include <libstb/secureboot.h> +#include <libstb/trustedboot.h> + +/* ibm,firmware-versions support */ +static char *version_buf; +static size_t version_buf_size = 0x2000; + +static void __flash_dt_add_fw_version(struct dt_node *fw_version, char* data) +{ + static bool first = true; + char *prop; + int version_len, i; + int len = strlen(data); + const char *skiboot_version; + const char * version_str[] = {"open-power", "buildroot", "skiboot", + "hostboot-binaries", "hostboot", "linux", + "petitboot", "occ", "capp-ucode", "sbe", + "machine-xml", "hcode"}; + + if (first) { + first = false; + + /* Increment past "key-" */ + if (memcmp(data, "open-power", strlen("open-power")) == 0) + prop = data + strlen("open-power"); + else + prop = strchr(data, '-'); + if (!prop) { + prlog(PR_DEBUG, + "FLASH: Invalid fw version format (%s)\n", data); + return; + } + prop++; + + dt_add_property_string(fw_version, "version", prop); + return; + } + + /* + * PNOR version strings are not easily consumable. Split them into + * property, value. + * + * Example input from PNOR : + * "open-power-firestone-v1.8" + * "linux-4.4.6-openpower1-8420e0f" + * + * Desired output in device tree: + * open-power = "firestone-v1.8"; + * linux = "4.4.6-openpower1-8420e0f"; + */ + for(i = 0; i < ARRAY_SIZE(version_str); i++) + { + version_len = strlen(version_str[i]); + if (len < version_len) + continue; + + if (memcmp(data, version_str[i], version_len) != 0) + continue; + + /* Found a match, add property */ + if (dt_find_property(fw_version, version_str[i])) + continue; + + /* Increment past "key-" */ + prop = data + version_len + 1; + dt_add_property_string(fw_version, version_str[i], prop); + + /* Sanity check against what Skiboot thinks its version is. */ + if (strncmp(version_str[i], "skiboot", + strlen("skiboot")) == 0) { + /* + * If Skiboot was built with Buildroot its version may + * include a 'skiboot-' prefix; ignore it. + */ + if (strncmp(version, "skiboot-", + strlen("skiboot-")) == 0) + skiboot_version = version + strlen("skiboot-"); + else + skiboot_version = version; + if (strncmp(prop, skiboot_version, + strlen(skiboot_version)) != 0) + prlog(PR_WARNING, "WARNING! Skiboot version does not match VERSION partition!\n"); + } + } +} + +void flash_dt_add_fw_version(void) +{ + uint8_t version_data[80]; + int rc; + int numbytes = 0, i = 0; + struct dt_node *fw_version; + + if (version_buf == NULL) + return; + + rc = wait_for_resource_loaded(RESOURCE_ID_VERSION, RESOURCE_SUBID_NONE); + if (rc != OPAL_SUCCESS) { + prlog(PR_WARNING, "FLASH: Failed to load VERSION data\n"); + free(version_buf); + return; + } + + fw_version = dt_new(dt_root, "ibm,firmware-versions"); + assert(fw_version); + + if (stb_is_container(version_buf, version_buf_size)) + numbytes += SECURE_BOOT_HEADERS_SIZE; + for ( ; (numbytes < version_buf_size) && version_buf[numbytes]; numbytes++) { + if (version_buf[numbytes] == '\n') { + version_data[i] = '\0'; + __flash_dt_add_fw_version(fw_version, version_data); + memset(version_data, 0, sizeof(version_data)); + i = 0; + continue; + } else if (version_buf[numbytes] == '\t') { + continue; /* skip tabs */ + } + + version_data[i++] = version_buf[numbytes]; + if (i == sizeof(version_data)) { + prlog(PR_WARNING, "VERSION item >%lu chars, skipping\n", + sizeof(version_data)); + break; + } + } + + free(version_buf); +} + +void flash_fw_version_preload(void) +{ + int rc; + + if (proc_gen < proc_gen_p9) + return; + + prlog(PR_INFO, "FLASH: Loading VERSION section\n"); + + version_buf = malloc(version_buf_size); + if (!version_buf) { + prlog(PR_WARNING, "FLASH: Failed to allocate memory\n"); + return; + } + + rc = start_preload_resource(RESOURCE_ID_VERSION, RESOURCE_SUBID_NONE, + version_buf, &version_buf_size); + if (rc != OPAL_SUCCESS) { + prlog(PR_WARNING, + "FLASH: Failed to start loading VERSION data\n"); + free(version_buf); + version_buf = NULL; + } +} |