aboutsummaryrefslogtreecommitdiffstats
path: root/roms/skiboot/core/flash-firmware-versions.c
diff options
context:
space:
mode:
Diffstat (limited to 'roms/skiboot/core/flash-firmware-versions.c')
-rw-r--r--roms/skiboot/core/flash-firmware-versions.c164
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;
+ }
+}