[[RFC PATCH] v2 06/14] lib/device-tree: Parse package versions from ibm, firmware-versions
Samuel Mendoza-Jonas
sam at mendozajonas.com
Thu Jan 18 16:05:09 AEDT 2018
On OpenPOWER platforms the current firmware versions are also advertised
via the 'ibm,firmware-versions' node in the device tree. These are
already split into name and version fields, so use this when available
rather than parsing the version strings from flash ourselves.
Signed-off-by: Samuel Mendoza-Jonas <sam at mendozajonas.com>
---
configure.ac | 12 +++--
discover/hostboot.c | 11 ++--
discover/hostboot.h | 5 +-
discover/platform-powerpc.c | 5 +-
lib/Makefile.am | 16 +++++-
lib/device-tree/device-tree.c | 117 ++++++++++++++++++++++++++++++++++++++++++
lib/device-tree/device-tree.h | 34 ++++++++++++
7 files changed, 185 insertions(+), 15 deletions(-)
create mode 100644 lib/device-tree/device-tree.c
create mode 100644 lib/device-tree/device-tree.h
diff --git a/configure.ac b/configure.ac
index fae1bd4..a9e5747 100644
--- a/configure.ac
+++ b/configure.ac
@@ -75,13 +75,17 @@ AC_CHECK_LIB([devmapper], [dm_task_create],
AC_ARG_WITH([fdt],
AS_HELP_STRING([--without-fdt],
- [Build without libfdt (default: no)]))
+ [Build without libfdt (default: no)])
+)
AS_IF([test "x$with_fdt" != "xno"],
AC_CHECK_LIB([fdt], [fdt_check_header],
- [FDT_LIBS=-lfdt; have_libfdt=yes]))
-
-AM_CONDITIONAL([HAVE_LIBFDT], [test x"$have_libfdt" = xyes])
+ [FDT_LIBS=-lfdt; have_libfdt=yes])
+)
+AS_IF([test "x$have_libfdt" = "xyes"],
+ [AC_DEFINE(FDT_SUPPORT, 1, [Enable libfdt support])]
+)
+AM_CONDITIONAL([HAVE_LIBFDT], [test x"$have_libfdt" = x"yes"])
AC_CHECK_HEADERS([stdarg.h])
AC_CHECK_HEADERS([varargs.h])
diff --git a/discover/hostboot.c b/discover/hostboot.c
index c63e363..54c6e0a 100644
--- a/discover/hostboot.c
+++ b/discover/hostboot.c
@@ -55,7 +55,7 @@ static int parse_hostboot_versions(void *ctx, char **strings,
return n_versions;
}
-void hostboot_load_versions(struct system_info *info)
+int hostboot_load_versions(struct system_info *info)
{
char **strings = NULL;
int n = 0;
@@ -63,13 +63,13 @@ void hostboot_load_versions(struct system_info *info)
n = flash_parse_version(info, &strings, true);
if (n < 0) {
pb_log("Failed to read platform versions for current side\n");
- return;
+ return n;
}
n = parse_hostboot_versions(info, strings, n, &info->platform_primary);
if (n < 0) {
pb_log("Failed to parse platform versions for current side\n");
- return;
+ return n;
}
info->n_primary = n;
@@ -80,16 +80,17 @@ void hostboot_load_versions(struct system_info *info)
n = flash_parse_version(info, &strings, false);
if (n < 0) {
pb_log("Failed to read platform versions for other side\n");
- return;
+ return n;
}
n = parse_hostboot_versions(info, strings, n, &info->platform_other);
if (n < 0) {
pb_log("Failed to parse platform versions for current side\n");
- return;
+ return n;
}
info->n_other = n;
talloc_free(strings);
+ return 0;
}
diff --git a/discover/hostboot.h b/discover/hostboot.h
index cb1e497..dd85336 100644
--- a/discover/hostboot.h
+++ b/discover/hostboot.h
@@ -5,11 +5,12 @@
#include <types/types.h>
#ifdef MTD_SUPPORT
-void hostboot_load_versions(struct system_info *info);
+int hostboot_load_versions(struct system_info *info);
#else
-static inline void hostboot_load_versions(struct system_info *info)
+static inline int hostboot_load_versions(struct system_info *info)
{
(void)info;
+ return 0;
}
#endif
#endif /* HOSTBOOT_H */
diff --git a/discover/platform-powerpc.c b/discover/platform-powerpc.c
index ed5733e..2478a00 100644
--- a/discover/platform-powerpc.c
+++ b/discover/platform-powerpc.c
@@ -46,7 +46,7 @@ struct platform_powerpc {
bool persistent);
int (*set_os_boot_sensor)(
struct platform_powerpc *platform);
- void (*get_platform_versions)(struct system_info *info);
+ int (*get_platform_versions)(struct system_info *info);
};
static const char *known_params[] = {
@@ -1324,7 +1324,8 @@ static int get_sysinfo(struct platform *p, struct system_info *sysinfo)
get_ipmi_bmc_versions(p, sysinfo);
if (platform->get_platform_versions)
- platform->get_platform_versions(sysinfo);
+ if (platform->get_platform_versions(sysinfo))
+ pb_log("Failed to read platform versions\n");
return 0;
}
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 6915314..429ce52 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -60,8 +60,12 @@ lib_libpbcore_la_SOURCES = \
lib/flash/flash.h \
lib/version/version.c \
lib/version/version.h \
+ lib/device-tree/device-tree.h
$(gpg_int_SOURCES)
+lib_libpbcore_la_LDFLAGS = \
+ $(AM_LDFLAGS)
+
if ENABLE_MTD
lib_libpbcore_la_SOURCES += \
lib/flash/flash.c
@@ -69,10 +73,18 @@ lib_libpbcore_la_SOURCES += \
lib_libpbcore_la_CPPFLAGS += \
$(AM_CPPFLAGS)
-lib_libpbcore_la_LDFLAGS = \
- $(AM_LDFLAGS) \
+lib_libpbcore_la_LDFLAGS += \
$(LIBFLASH_LIBS)
lib_libpbcore_la_SOURCES += \
lib/flash/flash.c
endif
+
+if HAVE_LIBFDT
+lib_libpbcore_la_SOURCES += \
+ lib/device-tree/device-tree.c
+
+lib_libpbcore_la_LDFLAGS += \
+ $(FDT_LIBS)
+
+endif
diff --git a/lib/device-tree/device-tree.c b/lib/device-tree/device-tree.c
new file mode 100644
index 0000000..bce884c
--- /dev/null
+++ b/lib/device-tree/device-tree.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2017 IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#define _GNU_SOURCE
+
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <libfdt.h>
+
+#include <log/log.h>
+#include <talloc/talloc.h>
+#include <file/file.h>
+
+#include "device-tree.h"
+
+int device_tree_find_firmware_versions(struct system_info *info)
+{
+ const char *path = "/sys/firmware/fdt";
+ struct firmware_version *versions = NULL;
+ unsigned int n_versions = 0;
+ int rc, offset, plen, dtb_len = 0;
+ char *buf = NULL;
+ const char *name;
+ const fdt32_t *prop;
+ void *dtb;
+
+ rc = read_file(info, path, &buf, &dtb_len);
+ if (rc) {
+ pb_log("device-tree: Failed to read dtb: %m\n");
+ return rc;
+ }
+
+ rc = fdt_check_header(buf);
+ if (rc) {
+ pb_log("device-tree: invalid dtb\n");
+ return rc;
+ }
+
+ if (dtb_len != (int)fdt_totalsize(buf)) {
+ pb_log("device-tree: dtb size mismatch\n");
+ dtb_len = fdt_totalsize(buf);
+ }
+
+ dtb = talloc_array(info, char, dtb_len);
+ if (!dtb) {
+ pb_log("Failed to allocate dtb\n");
+ return -1;
+ }
+
+ fdt_open_into(buf, dtb, dtb_len);
+
+ offset = fdt_subnode_offset(dtb, 0, "ibm,firmware-versions");
+ if (offset < 0) {
+ pb_log("Could not find ibm,firmware-versions node\n");
+ goto out;
+ }
+
+ offset = fdt_first_property_offset(dtb, offset);
+ if (offset < 0) {
+ pb_log("Could not find first version property\n");
+ goto out;
+ }
+
+ while (offset > 0) {
+ prop = fdt_getprop_by_offset(dtb, offset, &name, &plen);
+ if (!prop) {
+ pb_log("No property at %d?\n", offset);
+ continue;
+ }
+ if (strncmp(name, "phandle", strlen("phandle")) != 0) {
+ pb_log("\t%s - %s\n", name, (const char *)prop);
+ versions = talloc_realloc(info, versions,
+ struct firmware_version,
+ n_versions + 1);
+ if (!versions) {
+ pb_log("Failed to reallocate version array\n");
+ n_versions = 0;
+ rc = -1;
+ break;
+ }
+ versions[n_versions].name = talloc_strdup(versions,
+ name);
+ versions[n_versions].version = talloc_strdup(versions,
+ (const char *)prop);
+ n_versions++;
+ }
+
+ offset = fdt_next_property_offset(dtb, offset);
+ }
+
+ if (versions && n_versions) {
+ info->platform_primary = versions;
+ info->n_primary = n_versions;
+ }
+
+out:
+ if (buf)
+ talloc_free(buf);
+ if (dtb)
+ talloc_free(dtb);
+ return rc;
+}
diff --git a/lib/device-tree/device-tree.h b/lib/device-tree/device-tree.h
new file mode 100644
index 0000000..876e4a8
--- /dev/null
+++ b/lib/device-tree/device-tree.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2017 IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef DEVICE_TREE_H
+#define DEVICE_TREE_H
+
+#include "config.h"
+#include <types/types.h>
+
+#ifdef FDT_SUPPORT
+int device_tree_find_firmware_versions(struct system_info *info);
+#else
+static int device_tree_find_firmware_versions(struct system_info *info)
+{
+ (void)info;
+ return -1;
+}
+#endif
+
+#endif /* DEVICE_TREE_H */
--
2.15.1
More information about the Petitboot
mailing list