From: Joel Stanley Date: Tue, 21 Apr 2015 06:17:57 +0000 (+1000) Subject: discover/platform-powerpc: Set IPMI OS boot sensor X-Git-Tag: v1.0.0~74^2~16 X-Git-Url: http://git.ozlabs.org/?p=petitboot;a=commitdiff_plain;h=6600e73fe891d5006c34f694e97e37eefceb921d discover/platform-powerpc: Set IPMI OS boot sensor This is to indicate to a BMC that we have initiated OS boot. This patch manually parses the device tree for the sensor information. In the future this could be replaced by libfdt or similar. Discover the id of your OS Boot sensor: $ sudo ipmitool sensor get "OS Boot" Locating sensor record... Sensor ID : OS Boot (0x5a) Entity ID : 35.0 (Operating System) Sensor Type (Discrete): OS Boot (0x1f) Sensor Reading : 0h Event Message Control : Per-threshold Assertion Events : OS Boot [boot completed - device not specified] Assertions Enabled : OS Boot [A: boot completed] [C: boot completed] [PXE boot completed] [Diagnostic boot completed] [CD-ROM boot completed] [ROM boot completed] [boot completed - device not specified] [Installation started] [Installation completed] [Installation aborted] [Installation failed] OEM : 0 In this case it is 0x1f. Note that the sesnor is currently asserted iwth boot completed - device not specified. Test by clearing all assertions in the OS Boot sensor: $ sudo ipmitool raw 0x04 0x30 0x5a 0x30 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 $ sudo ipmitool sensor get "OS Boot" Locating sensor record... Sensor ID : OS Boot (0x5a) Entity ID : 35.0 (Operating System) Sensor Type (Discrete): OS Boot (0x1f) Sensor Reading : 0h Event Message Control : Per-threshold Assertions Enabled : OS Boot [A: boot completed] [C: boot completed] [PXE boot completed] [Diagnostic boot completed] [CD-ROM boot completed] [ROM boot completed] [boot completed - device not specified] [Installation started] [Installation completed] [Installation aborted] [Installation failed] OEM : 0 Then reboot your system. The assertion event should once more say "boot completed - device not specified". Signed-off-by: Joel Stanley --- diff --git a/discover/Makefile.am b/discover/Makefile.am index 1e4df0b..7808110 100644 --- a/discover/Makefile.am +++ b/discover/Makefile.am @@ -71,6 +71,8 @@ discover_platform_ro_SOURCES = \ discover/platform.h \ discover/ipmi.c \ discover/ipmi.h \ + discover/dt.c \ + discover/dt.h \ discover/platform-powerpc.c discover_platform_ro_LINK = \ diff --git a/discover/dt.c b/discover/dt.c new file mode 100644 index 0000000..a7383e1 --- /dev/null +++ b/discover/dt.c @@ -0,0 +1,61 @@ +#include +#include +#include +#include +#include + +#include +#include + +#include "dt.h" + +static int filter_sensors(const struct dirent *ent) +{ + /* Check for prefix "sensor@" */ + return strncmp(ent->d_name, "sensor@", strlen("sensor@")) == 0; +} + +int get_ipmi_sensor(void *t, enum ipmi_sensor_ids sensor_id) +{ + int rc, len, n; + struct dirent **namelist; + char *buf, *filename; + const char sensor_dir[] = "/proc/device-tree/bmc/sensors/"; + + n = scandir(sensor_dir, &namelist, filter_sensors, alphasort); + if (n <= 0) + return -1; + + while (n--) { + filename = talloc_asprintf(t, "%s%s/ipmi-sensor-type", + sensor_dir, namelist[n]->d_name); + rc = read_file(t, filename, &buf, &len); + if (rc == 0 && len == 4 && + __be32_to_cpu(*(uint32_t *)buf) == sensor_id) + break; + free(namelist[n]); + } + if (n < 0) { + rc = -1; + goto out; + } + + filename = talloc_asprintf(t, "%s%s/reg", sensor_dir, + namelist[n]->d_name); + /* Free the rest of the scandir strings, if there are any */ + do { + free(namelist[n]); + } while (n-- > 0); + + rc = read_file(t, filename, &buf, &len); + if (rc != 0 || len != 4) { + rc = -1; + goto out; + } + + rc = __be32_to_cpu(*(uint32_t *)buf); + +out: + free(namelist); + return rc; +} diff --git a/discover/dt.h b/discover/dt.h new file mode 100644 index 0000000..4692d04 --- /dev/null +++ b/discover/dt.h @@ -0,0 +1,8 @@ +#ifndef _DT_H +#define _DT_H + +#include "ipmi.h" + +int get_ipmi_sensor(void *t, enum ipmi_sensor_ids sensor_id); + +#endif /* _IPMI_H */ diff --git a/discover/ipmi.h b/discover/ipmi.h index e60ff61..83f2910 100644 --- a/discover/ipmi.h +++ b/discover/ipmi.h @@ -5,12 +5,14 @@ #include enum ipmi_netfn { - IPMI_NETFN_CHASSIS = 0x0, + IPMI_NETFN_CHASSIS = 0x0, + IPMI_NETFN_SE = 0x04, }; enum ipmi_cmd { IPMI_CMD_CHASSIS_SET_SYSTEM_BOOT_OPTIONS = 0x08, IPMI_CMD_CHASSIS_GET_SYSTEM_BOOT_OPTIONS = 0x09, + IPMI_CMD_SENSOR_SET = 0x30, }; enum ipmi_bootdev { @@ -22,6 +24,10 @@ enum ipmi_bootdev { IPMI_BOOTDEV_SETUP = 0x6, }; +enum ipmi_sensor_ids { + IPMI_SENSOR_ID_OS_BOOT = 0x1F, +}; + struct ipmi; bool ipmi_present(void); diff --git a/discover/platform-powerpc.c b/discover/platform-powerpc.c index a293ce9..4cc91fa 100644 --- a/discover/platform-powerpc.c +++ b/discover/platform-powerpc.c @@ -17,6 +17,7 @@ #include "platform.h" #include "ipmi.h" +#include "dt.h" static const char *partition = "common"; static const char *sysparams_dir = "/sys/firmware/opal/sysparams/"; @@ -39,6 +40,8 @@ struct platform_powerpc { uint8_t *bootdev, bool *persistent); int (*clear_ipmi_bootdev)( struct platform_powerpc *platform); + int (*set_os_boot_sensor)( + struct platform_powerpc *platform); }; static const char *known_params[] = { @@ -792,6 +795,42 @@ static int get_ipmi_bootdev_ipmi(struct platform_powerpc *platform, return 0; } +static int set_ipmi_os_boot_sensor(struct platform_powerpc *platform) +{ + int sensor_number; + uint16_t resp_len; + uint8_t resp[1]; + uint8_t req[] = { + 0x00, /* sensor number: os boot */ + 0x10, /* operation: set assertion bits */ + 0x00, /* sensor reading: none */ + 0x40, /* assertion mask lsb: set state 6 */ + 0x00, /* assertion mask msb: none */ + 0x00, /* deassertion mask lsb: none */ + 0x00, /* deassertion mask msb: none */ + 0x00, /* event data 1: none */ + 0x00, /* event data 2: none */ + 0x00, /* event data 3: none */ + }; + + sensor_number = get_ipmi_sensor(platform, IPMI_SENSOR_ID_OS_BOOT); + if (sensor_number < 0) { + pb_log("Couldn't find OS boot sensor in device tree\n"); + return -1; + } + + req[0] = sensor_number; + + resp_len = sizeof(resp); + + ipmi_transaction(platform->ipmi, IPMI_NETFN_SE, + IPMI_CMD_SENSOR_SET, + req, sizeof(req), + resp, &resp_len, + ipmi_timeout); return 0; + + return 0; +} static int load_config(struct platform *p, struct config *config) { @@ -838,6 +877,9 @@ static void pre_boot(struct platform *p, const struct config *config) if (!config->ipmi_bootdev_persistent && platform->clear_ipmi_bootdev) platform->clear_ipmi_bootdev(platform); + + if (platform->set_os_boot_sensor) + platform->set_os_boot_sensor(platform); } static int get_sysinfo(struct platform *p, struct system_info *sysinfo) @@ -875,7 +917,7 @@ static bool probe(struct platform *p, void *ctx) if (!S_ISDIR(statbuf.st_mode)) return false; - platform = talloc(ctx, struct platform_powerpc); + platform = talloc_zero(ctx, struct platform_powerpc); list_init(&platform->params); p->platform_data = platform; @@ -885,6 +927,7 @@ static bool probe(struct platform *p, void *ctx) platform->ipmi = ipmi_open(platform); platform->get_ipmi_bootdev = get_ipmi_bootdev_ipmi; platform->clear_ipmi_bootdev = clear_ipmi_bootdev_ipmi; + platform->set_os_boot_sensor = set_ipmi_os_boot_sensor; } else if (!stat(sysparams_dir, &statbuf)) { pb_debug("platform: using sysparams for IPMI paramters\n");