[RFC PATCH 6/7] discover: Add platform support for attribute overrides

Samuel Mendoza-Jonas sam.mj at au1.ibm.com
Mon Nov 30 14:13:18 AEDT 2015


Load attribute information on startup, and support
PB_PROTOCOL_ACTION_FIRMWARE messages to and from clients.
If an update is received from a client and is successfully processed,
the server must immediately reboot the machine.
This patch adds functionality to both platform-powerpc and generic
platform code for testing, the final version will be platform specific.

Signed-off-by: Samuel Mendoza-Jonas <sam.mj at au1.ibm.com>
---
 discover/Makefile.am        | 11 +++++++++++
 discover/device-handler.c   | 21 +++++++++++++++++++++
 discover/device-handler.h   |  2 ++
 discover/discover-server.c  | 36 ++++++++++++++++++++++++++++++++++++
 discover/platform-powerpc.c | 31 +++++++++++++++++++++++++++++++
 discover/platform.c         | 37 +++++++++++++++++++++++++++++++++++++
 discover/platform.h         |  8 ++++++++
 7 files changed, 146 insertions(+)

diff --git a/discover/Makefile.am b/discover/Makefile.am
index 1672035..1c95117 100644
--- a/discover/Makefile.am
+++ b/discover/Makefile.am
@@ -79,7 +79,18 @@ discover_platform_ro_SOURCES = \
 	discover/ipmi.h \
 	discover/dt.c \
 	discover/dt.h \
+	discover/hostboot.c \
+	discover/hostboot.h \
 	discover/platform-powerpc.c
 
+discover_platform_ro_LDFLAGS = \
+	`xml2-config --libs` \
+	$(core_lib) \
+	$(UDEV_LIBS)
+
+discover_platform_ro_CPPFLAGS = \
+	$(AM_CPPFLAGS) \
+	`xml2-config --cflags`
+
 discover_platform_ro_LINK = \
 	$(LD) -r -o $@
diff --git a/discover/device-handler.c b/discover/device-handler.c
index bfe5fff..ae10d63 100644
--- a/discover/device-handler.c
+++ b/discover/device-handler.c
@@ -1057,6 +1057,27 @@ void device_handler_update_config(struct device_handler *handler,
 	device_handler_reinit(handler);
 }
 
+void device_handler_update_platform_options(struct platform_options *options)
+{
+	int rc;
+
+	rc = platform_options_update(options);
+	if (rc < 0) {
+		/* There was an error updating platform attributes, avoid
+		 * rebooting so it can be investigated */
+		pb_log("WARNING: Platform attribute update failed\n");
+		return;
+	}
+	if (rc == 0) {
+		pb_log("No platform updates performed - continuing\n");
+		return;
+	}
+
+	pb_log("%d platform updates performed - REBOOTING\n", rc);
+	//reboot
+	exit(0);
+}
+
 static char *device_from_addr(void *ctx, struct pb_url *url)
 {
 	char *ipaddr, *buf, *tok, *dev = NULL;
diff --git a/discover/device-handler.h b/discover/device-handler.h
index d18910a..ce35b26 100644
--- a/discover/device-handler.h
+++ b/discover/device-handler.h
@@ -14,6 +14,7 @@ struct event;
 struct device;
 struct waitset;
 struct config;
+struct platform_options;
 
 struct discover_device {
 	struct device		*device;
@@ -132,6 +133,7 @@ void device_handler_boot(struct device_handler *handler,
 void device_handler_cancel_default(struct device_handler *handler);
 void device_handler_update_config(struct device_handler *handler,
 		struct config *config);
+void device_handler_update_platform_options(struct platform_options *options);
 void device_handler_process_url(struct device_handler *handler,
 		const char *url);
 void device_handler_reinit(struct device_handler *handler);
diff --git a/discover/discover-server.c b/discover/discover-server.c
index e4f3b67..a5fb972 100644
--- a/discover/discover-server.c
+++ b/discover/discover-server.c
@@ -210,10 +210,29 @@ static int write_config_message(struct discover_server *server,
 	return client_write_message(server, client, message);
 }
 
+static int write_platform_message(struct discover_server *server,
+		struct client *client, const struct platform_options *options)
+{
+	struct pb_protocol_message *message;
+	int len;
+
+	len = pb_protocol_platform_options_len(options);
+
+	message = pb_protocol_create_message(client,
+			PB_PROTOCOL_ACTION_FIRMWARE, len);
+	if (!message)
+		return -1;
+
+	pb_protocol_serialise_platform_options(options, message->payload, len);
+
+	return client_write_message(server, client, message);
+}
+
 static int discover_server_process_message(void *arg)
 {
 	struct pb_protocol_message *message;
 	struct boot_command *boot_command;
+	struct platform_options *options;
 	struct client *client = arg;
 	struct config *config;
 	char *url;
@@ -269,6 +288,18 @@ static int discover_server_process_message(void *arg)
 		device_handler_process_url(client->server->device_handler, url);
 		break;
 
+	case PB_PROTOCOL_ACTION_FIRMWARE:
+		options = talloc_zero(client, struct platform_options);
+
+		rc = pb_protocol_deserialise_platform_options(options, message);
+		if (rc) {
+			pb_log("%s: no options?", __func__);
+			return 0;
+		}
+
+		device_handler_update_platform_options(options);
+		break;
+
 	default:
 		pb_log("%s: invalid action %d\n", __func__, message->action);
 		return 0;
@@ -313,6 +344,11 @@ static int discover_server_process_connection(void *arg)
 	if (rc)
 		return 0;
 
+	/* send platform options to client */
+	rc = write_platform_message(server, client, platform_options_get());
+	if (rc)
+		return 0;
+
 	/* send existing devices to client */
 	n_devices = device_handler_get_device_count(server->device_handler);
 	for (i = 0; i < n_devices; i++) {
diff --git a/discover/platform-powerpc.c b/discover/platform-powerpc.c
index 23e63c1..4fd92c3 100644
--- a/discover/platform-powerpc.c
+++ b/discover/platform-powerpc.c
@@ -14,7 +14,9 @@
 #include <list/list.h>
 #include <log/log.h>
 #include <process/process.h>
+#include <types/types.h>
 
+#include "hostboot.h"
 #include "platform.h"
 #include "ipmi.h"
 #include "dt.h"
@@ -22,6 +24,8 @@
 static const char *partition = "common";
 static const char *sysparams_dir = "/sys/firmware/opal/sysparams/";
 static const char *devtree_dir = "/proc/device-tree/";
+static const char *xml_path = "/usr/share/hostboot_example.xml";
+static const char *mtd_path = "/dev/mtd";
 static const int ipmi_timeout = 5000; /* milliseconds. */
 
 struct param {
@@ -43,6 +47,7 @@ struct platform_powerpc {
 				bool persistent);
 	int 		(*set_os_boot_sensor)(
 				struct platform_powerpc *platform);
+	//TODO function pointers since libflash only relevant on BMC machines
 };
 
 static const char *known_params[] = {
@@ -989,6 +994,30 @@ static int set_ipmi_os_boot_sensor(struct platform_powerpc *platform)
 	return 0;
 }
 
+static int load_options(struct platform *p, struct platform_options *options)
+{
+	options = talloc(p, struct platform_options);
+	load_hostboot(options, xml_path, mtd_path);
+	return 0;
+}
+
+static int save_options(struct platform *p, struct platform_options *options)
+{
+	int rc, updated = 0;
+	unsigned int i;
+	(void)p;
+
+	for (i = 0; i < options->n_options; i++) {
+		rc = update_platform_option(options, options->options[i],
+					    mtd_path);
+		if (rc < 0)
+			break;
+		updated += rc;
+	}
+
+	return rc < 0 ? rc : updated;
+}
+
 static int load_config(struct platform *p, struct config *config)
 {
 	struct platform_powerpc *platform = to_platform_powerpc(p);
@@ -1107,6 +1136,8 @@ static struct platform platform_powerpc = {
 	.save_config		= save_config,
 	.pre_boot		= pre_boot,
 	.get_sysinfo		= get_sysinfo,
+	.load_options		= load_options,
+	.save_options		= save_options,
 };
 
 register_platform(platform_powerpc);
diff --git a/discover/platform.c b/discover/platform.c
index 5f448f1..4e832b6 100644
--- a/discover/platform.c
+++ b/discover/platform.c
@@ -11,10 +11,14 @@
 #include <talloc/talloc.h>
 
 #include "platform.h"
+#include "hostboot.h"
 
 void			*platform_ctx;
 static struct platform	*platform;
 static struct config	*config;
+static struct platform_options *options;
+static const char	*mtd_path = "/path/to/dummy/mtd";
+static const char	*xml_path = "/path/to/hostboot_example.xml";
 
 static const char *kernel_cmdline_debug = "petitboot.debug";
 
@@ -159,9 +163,13 @@ int platform_init(void *ctx)
 		pb_log("Detected platform type: %s\n", platform->name);
 		if (platform->load_config)
 			platform->load_config(platform, config);
+		if (platform->load_options)
+			platform->load_options(platform, options);
 	} else {
 		pb_log("No platform type detected, some platform-specific "
 				"functionality will be disabled\n");
+		options = talloc(platform_ctx, struct platform_options);
+		load_hostboot(options, xml_path, mtd_path);
 	}
 
 	dump_config(config);
@@ -212,6 +220,30 @@ int config_set(struct config *newconfig)
 	return rc;
 }
 
+int platform_options_update(struct platform_options *options)
+{
+	int rc, updated = 0;
+	unsigned int i;
+
+	if (platform && platform->save_options) {
+		rc = updated = platform->save_options( platform, options);
+		goto out;
+	}
+
+	pb_log("Performing DEBUG platform options update\n");
+
+	for (i = 0; i < options->n_options; i++) {
+		rc = update_platform_option(options, options->options[i],
+					    mtd_path);
+		if (rc < 0)
+			break;
+		updated += rc;
+	}
+
+out:
+	return rc < 0 ? rc : updated;
+}
+
 /* A non-exported function to allow the test infrastructure to initialise
  * (and change) the configuration variables */
 struct parser_test;
@@ -229,6 +261,11 @@ const struct config *config_get(void)
 	return config;
 }
 
+const struct platform_options *platform_options_get(void)
+{
+	return options;
+}
+
 void config_set_autoboot(bool autoboot_enabled)
 {
 	config->autoboot_enabled = autoboot_enabled;
diff --git a/discover/platform.h b/discover/platform.h
index 5aa8e3f..3e0c454 100644
--- a/discover/platform.h
+++ b/discover/platform.h
@@ -11,6 +11,10 @@ struct platform {
 	void		(*pre_boot)(struct platform *,
 				const struct config *);
 	int		(*get_sysinfo)(struct platform *, struct system_info *);
+	int		(*load_options)(struct platform *,
+					struct platform_options *);
+	int		(*save_options)(struct platform *,
+					struct platform_options *);
 	uint16_t	dhcp_arch_id;
 	void		*platform_data;
 };
@@ -29,6 +33,10 @@ void config_set_autoboot(bool autoboot_enabled);
 /* for use by the platform-specific storage code */
 void config_set_defaults(struct config *config);
 
+/* platform-specific options */
+const struct platform_options *platform_options_get(void);
+int platform_options_update(struct platform_options *options);
+
 #define __platform_ptrname(_n) __platform_ ## _n
 #define  _platform_ptrname(_n) __platform_ptrname(_n)
 
-- 
2.6.2



More information about the Petitboot mailing list