[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