blob: 43c3fe32ca8fcf824ce1090decb3b9bb6a1582ac [file] [log] [blame]
Adriana Kobylak40814c62015-10-27 15:58:44 -05001#include "chassishandler.h"
Patrick Williams37af7332016-09-02 21:21:42 -05002#include "host-ipmid/ipmid-api.h"
Ratan Guptadcb10672017-07-10 10:33:50 +05303#include "types.hpp"
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05004#include "ipmid.hpp"
5#include "settings.hpp"
Ratan Guptacc8feb42017-07-25 21:52:10 +05306#include "utils.hpp"
Ratan Guptadcb10672017-07-10 10:33:50 +05307
Adriana Kobylak40814c62015-10-27 15:58:44 -05008#include <stdio.h>
Ratan Guptafd28dd72016-08-01 04:58:01 -05009#include <stdlib.h>
Adriana Kobylak40814c62015-10-27 15:58:44 -050010#include <stdint.h>
Brad Bishop35518682016-07-22 08:35:41 -040011#include <mapper.h>
Ratan Guptafd28dd72016-08-01 04:58:01 -050012#include <arpa/inet.h>
13#include <netinet/in.h>
14#include <limits.h>
15#include <string.h>
16#include <endian.h>
17#include <sstream>
18#include <array>
Andrew Geisslera6e3a302017-05-31 19:34:00 -050019#include <fstream>
James Feist5bfbde32017-11-22 13:40:53 -080020#include <future>
21#include <chrono>
Andrew Geisslera6e3a302017-05-31 19:34:00 -050022#include <experimental/filesystem>
Ratan Guptadcb10672017-07-10 10:33:50 +053023#include <string>
Deepak Kodihalli8cc19362017-07-21 11:18:38 -050024#include <map>
Ratan Guptadcb10672017-07-10 10:33:50 +053025
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +053026#include <phosphor-logging/log.hpp>
Ratan Guptadcb10672017-07-10 10:33:50 +053027#include <phosphor-logging/elog-errors.hpp>
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +053028#include <xyz/openbmc_project/State/Host/server.hpp>
Ratan Guptadcb10672017-07-10 10:33:50 +053029#include "xyz/openbmc_project/Common/error.hpp"
30
31#include <sdbusplus/bus.hpp>
32#include <sdbusplus/server/object.hpp>
Deepak Kodihalli8cc19362017-07-21 11:18:38 -050033#include <xyz/openbmc_project/Control/Boot/Source/server.hpp>
34#include <xyz/openbmc_project/Control/Boot/Mode/server.hpp>
Deepak Kodihalli18b70d12017-07-21 13:36:33 -050035#include <xyz/openbmc_project/Control/Power/RestorePolicy/server.hpp>
Ratan Guptadcb10672017-07-10 10:33:50 +053036
Vishwanatha Subbannab891a572017-03-31 11:34:48 +053037#include "config.h"
ratagupta6f6bff2016-04-04 06:20:11 -050038
39//Defines
Ratan Guptafd28dd72016-08-01 04:58:01 -050040#define SET_PARM_VERSION 0x01
41#define SET_PARM_BOOT_FLAGS_PERMANENT 0x40 //boot flags data1 7th bit on
ratagupta6f6bff2016-04-04 06:20:11 -050042#define SET_PARM_BOOT_FLAGS_VALID_ONE_TIME 0x80 //boot flags data1 8th bit on
Ratan Guptafd28dd72016-08-01 04:58:01 -050043#define SET_PARM_BOOT_FLAGS_VALID_PERMANENT 0xC0 //boot flags data1 7 & 8 bit on
ratagupta6f6bff2016-04-04 06:20:11 -050044
Ratan Guptafd28dd72016-08-01 04:58:01 -050045constexpr size_t SIZE_MAC = 18;
46constexpr size_t SIZE_BOOT_OPTION = (uint8_t)BootOptionResponseSize::
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -050047 OPAL_NETWORK_SETTINGS;//Maximum size of the boot option parametrs
Ratan Guptafd28dd72016-08-01 04:58:01 -050048constexpr size_t SIZE_PREFIX = 7;
49constexpr size_t MAX_PREFIX_VALUE = 32;
50constexpr size_t SIZE_COOKIE = 4;
51constexpr size_t SIZE_VERSION = 2;
James Feist5bfbde32017-11-22 13:40:53 -080052constexpr size_t DEFAULT_IDENTIFY_TIME_OUT = 15;
Ratan Gupta6ec7daa2017-07-15 14:13:01 +053053
Ratan Guptafd28dd72016-08-01 04:58:01 -050054//PetiBoot-Specific
Ratan Gupta6ec7daa2017-07-15 14:13:01 +053055static constexpr uint8_t net_conf_initial_bytes[] = {0x80, 0x21, 0x70, 0x62,
56 0x21, 0x00, 0x01, 0x06};
Ratan Guptafd28dd72016-08-01 04:58:01 -050057
58static constexpr size_t COOKIE_OFFSET = 1;
59static constexpr size_t VERSION_OFFSET = 5;
Ratan Gupta6ec7daa2017-07-15 14:13:01 +053060static constexpr size_t ADDR_SIZE_OFFSET = 8;
Ratan Guptafd28dd72016-08-01 04:58:01 -050061static constexpr size_t MAC_OFFSET = 9;
62static constexpr size_t ADDRTYPE_OFFSET = 16;
63static constexpr size_t IPADDR_OFFSET = 17;
ratagupta6f6bff2016-04-04 06:20:11 -050064
shgoupfd84fbbf2015-12-17 10:05:51 +080065
Adriana Kobylak40814c62015-10-27 15:58:44 -050066void register_netfn_chassis_functions() __attribute__((constructor));
67
shgoupfd84fbbf2015-12-17 10:05:51 +080068// Host settings in dbus
69// Service name should be referenced by connection name got via object mapper
70const char *settings_object_name = "/org/openbmc/settings/host0";
71const char *settings_intf_name = "org.freedesktop.DBus.Properties";
72const char *host_intf_name = "org.openbmc.settings.Host";
James Feist5bfbde32017-11-22 13:40:53 -080073const char *identify_led_object_name =
74 "/xyz/openbmc_project/led/groups/enclosure_identify";
shgoupfd84fbbf2015-12-17 10:05:51 +080075
Ratan Guptadcb10672017-07-10 10:33:50 +053076constexpr auto SETTINGS_ROOT = "/";
77constexpr auto SETTINGS_MATCH = "host0";
Ratan Guptadcb10672017-07-10 10:33:50 +053078
79constexpr auto IP_INTERFACE = "xyz.openbmc_project.Network.IP";
80constexpr auto MAC_INTERFACE = "xyz.openbmc_project.Network.MACAddress";
81
Ratan Guptadcb10672017-07-10 10:33:50 +053082
Nan Li8d15fb42016-08-16 22:29:40 +080083typedef struct
84{
85 uint8_t cap_flags;
86 uint8_t fru_info_dev_addr;
87 uint8_t sdr_dev_addr;
88 uint8_t sel_dev_addr;
89 uint8_t system_management_dev_addr;
90 uint8_t bridge_dev_addr;
91}__attribute__((packed)) ipmi_chassis_cap_t;
92
Nan Lifdd8ec52016-08-28 03:57:40 +080093typedef struct
94{
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -050095 uint8_t cur_power_state;
96 uint8_t last_power_event;
97 uint8_t misc_power_state;
98 uint8_t front_panel_button_cap_status;
Nan Lifdd8ec52016-08-28 03:57:40 +080099}__attribute__((packed)) ipmi_get_chassis_status_t;
100
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530101// Phosphor Host State manager
102namespace State = sdbusplus::xyz::openbmc_project::State::server;
103
Andrew Geisslera6e3a302017-05-31 19:34:00 -0500104namespace fs = std::experimental::filesystem;
105
Ratan Guptadcb10672017-07-10 10:33:50 +0530106using namespace phosphor::logging;
107using namespace sdbusplus::xyz::openbmc_project::Common::Error;
108
Deepak Kodihalli8cc19362017-07-21 11:18:38 -0500109namespace chassis
110{
111namespace internal
112{
113
114constexpr auto bootModeIntf = "xyz.openbmc_project.Control.Boot.Mode";
115constexpr auto bootSourceIntf = "xyz.openbmc_project.Control.Boot.Source";
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500116constexpr auto powerRestoreIntf =
117 "xyz.openbmc_project.Control.Power.RestorePolicy";
Deepak Kodihalli8cc19362017-07-21 11:18:38 -0500118sdbusplus::bus::bus dbus(ipmid_get_sd_bus_connection());
119
120namespace cache
121{
122
123settings::Objects objects(dbus,
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500124 {bootModeIntf, bootSourceIntf, powerRestoreIntf});
Deepak Kodihalli8cc19362017-07-21 11:18:38 -0500125
126} // namespace cache
127} // namespace internal
128} // namespace chassis
129
Ratan Guptadcb10672017-07-10 10:33:50 +0530130//TODO : Can remove the below function as we have
131// new functions which uses sdbusplus.
132//
133// openbmc/openbmc#1489
ratagupta6f6bff2016-04-04 06:20:11 -0500134int dbus_get_property(const char *name, char **buf)
shgoupfd84fbbf2015-12-17 10:05:51 +0800135{
136 sd_bus_error error = SD_BUS_ERROR_NULL;
137 sd_bus_message *m = NULL;
138 sd_bus *bus = NULL;
139 char *temp_buf = NULL;
140 char *connection = NULL;
141 int r;
142
Brad Bishop35518682016-07-22 08:35:41 -0400143 // Get the system bus where most system services are provided.
144 bus = ipmid_get_sd_bus_connection();
shgoupfd84fbbf2015-12-17 10:05:51 +0800145
Brad Bishop35518682016-07-22 08:35:41 -0400146 r = mapper_get_service(bus, settings_object_name, &connection);
shgoupfd84fbbf2015-12-17 10:05:51 +0800147 if (r < 0) {
Brad Bishop819ddd42016-10-05 21:19:19 -0400148 fprintf(stderr, "Failed to get %s connection: %s\n",
149 settings_object_name, strerror(-r));
shgoupfd84fbbf2015-12-17 10:05:51 +0800150 goto finish;
151 }
152
shgoupfd84fbbf2015-12-17 10:05:51 +0800153 /*
154 * Bus, service, object path, interface and method are provided to call
155 * the method.
156 * Signatures and input arguments are provided by the arguments at the
157 * end.
158 */
159 r = sd_bus_call_method(bus,
160 connection, /* service to contact */
161 settings_object_name, /* object path */
162 settings_intf_name, /* interface name */
163 "Get", /* method name */
164 &error, /* object to return error in */
165 &m, /* return message on success */
166 "ss", /* input signature */
167 host_intf_name, /* first argument */
ratagupta6f6bff2016-04-04 06:20:11 -0500168 name); /* second argument */
shgoupfd84fbbf2015-12-17 10:05:51 +0800169
170 if (r < 0) {
171 fprintf(stderr, "Failed to issue method call: %s\n", error.message);
172 goto finish;
173 }
174
175 /*
176 * The output should be parsed exactly the same as the output formatting
177 * specified.
178 */
179 r = sd_bus_message_read(m, "v", "s", &temp_buf);
180 if (r < 0) {
181 fprintf(stderr, "Failed to parse response message: %s\n", strerror(-r));
182 goto finish;
183 }
184
Matthew Barth56181052017-01-23 09:36:29 -0600185 *buf = strdup(temp_buf);
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500186 /* *buf = (char*) malloc(strlen(temp_buf));
shgoupfd84fbbf2015-12-17 10:05:51 +0800187 if (*buf) {
188 strcpy(*buf, temp_buf);
189 }
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500190 */
shgoupfd84fbbf2015-12-17 10:05:51 +0800191 printf("IPMID boot option property get: {%s}.\n", (char *) temp_buf);
192
193finish:
194 sd_bus_error_free(&error);
195 sd_bus_message_unref(m);
196 free(connection);
197
198 return r;
199}
200
Ratan Guptadcb10672017-07-10 10:33:50 +0530201//TODO : Can remove the below function as we have
202// new functions which uses sdbusplus.
203//
204// openbmc/openbmc#1489
205
ratagupta6f6bff2016-04-04 06:20:11 -0500206int dbus_set_property(const char * name, const char *value)
shgoupfd84fbbf2015-12-17 10:05:51 +0800207{
208 sd_bus_error error = SD_BUS_ERROR_NULL;
209 sd_bus_message *m = NULL;
210 sd_bus *bus = NULL;
211 char *connection = NULL;
212 int r;
213
Brad Bishop35518682016-07-22 08:35:41 -0400214 // Get the system bus where most system services are provided.
215 bus = ipmid_get_sd_bus_connection();
shgoupfd84fbbf2015-12-17 10:05:51 +0800216
Brad Bishop35518682016-07-22 08:35:41 -0400217 r = mapper_get_service(bus, settings_object_name, &connection);
shgoupfd84fbbf2015-12-17 10:05:51 +0800218 if (r < 0) {
Brad Bishop819ddd42016-10-05 21:19:19 -0400219 fprintf(stderr, "Failed to get %s connection: %s\n",
220 settings_object_name, strerror(-r));
shgoupfd84fbbf2015-12-17 10:05:51 +0800221 goto finish;
222 }
223
shgoupfd84fbbf2015-12-17 10:05:51 +0800224 /*
225 * Bus, service, object path, interface and method are provided to call
226 * the method.
227 * Signatures and input arguments are provided by the arguments at the
228 * end.
229 */
230 r = sd_bus_call_method(bus,
231 connection, /* service to contact */
232 settings_object_name, /* object path */
233 settings_intf_name, /* interface name */
234 "Set", /* method name */
235 &error, /* object to return error in */
236 &m, /* return message on success */
237 "ssv", /* input signature */
238 host_intf_name, /* first argument */
ratagupta6f6bff2016-04-04 06:20:11 -0500239 name, /* second argument */
shgoupfd84fbbf2015-12-17 10:05:51 +0800240 "s", /* third argument */
ratagupta6f6bff2016-04-04 06:20:11 -0500241 value); /* fourth argument */
shgoupfd84fbbf2015-12-17 10:05:51 +0800242
243 if (r < 0) {
244 fprintf(stderr, "Failed to issue method call: %s\n", error.message);
245 goto finish;
246 }
247
ratagupta6f6bff2016-04-04 06:20:11 -0500248 printf("IPMID boot option property set: {%s}.\n", value);
shgoupfd84fbbf2015-12-17 10:05:51 +0800249
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500250 finish:
shgoupfd84fbbf2015-12-17 10:05:51 +0800251 sd_bus_error_free(&error);
252 sd_bus_message_unref(m);
253 free(connection);
254
255 return r;
256}
257
Adriana Kobylak40814c62015-10-27 15:58:44 -0500258struct get_sys_boot_options_t {
259 uint8_t parameter;
260 uint8_t set;
261 uint8_t block;
262} __attribute__ ((packed));
263
shgoupfd84fbbf2015-12-17 10:05:51 +0800264struct get_sys_boot_options_response_t {
265 uint8_t version;
266 uint8_t parm;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500267 uint8_t data[SIZE_BOOT_OPTION];
shgoupfd84fbbf2015-12-17 10:05:51 +0800268} __attribute__ ((packed));
269
270struct set_sys_boot_options_t {
271 uint8_t parameter;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500272 uint8_t data[SIZE_BOOT_OPTION];
shgoupfd84fbbf2015-12-17 10:05:51 +0800273} __attribute__ ((packed));
274
Ratan Guptafd28dd72016-08-01 04:58:01 -0500275
Ratan Guptadcb10672017-07-10 10:33:50 +0530276int getHostNetworkData(get_sys_boot_options_response_t* respptr)
Ratan Guptafd28dd72016-08-01 04:58:01 -0500277{
Ratan Guptadcb10672017-07-10 10:33:50 +0530278 ipmi::PropertyMap properties;
279 int rc = 0;
Ratan Gupta8c31d232017-08-13 05:49:43 +0530280 uint8_t addrSize = ipmi::network::IPV4_ADDRESS_SIZE_BYTE;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500281
Ratan Guptadcb10672017-07-10 10:33:50 +0530282 try
283 {
284 //TODO There may be cases where an interface is implemented by multiple
285 // objects,to handle such cases we are interested on that object
286 // which are on interested busname.
287 // Currenlty mapper doesn't give the readable busname(gives busid)
288 // so we can't match with bus name so giving some object specific info
289 // as SETTINGS_MATCH.
290 // Later SETTINGS_MATCH will be replaced with busname.
Ratan Guptafd28dd72016-08-01 04:58:01 -0500291
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530292 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
Ratan Guptadcb10672017-07-10 10:33:50 +0530293
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530294 auto ipObjectInfo = ipmi::getDbusObject(bus, IP_INTERFACE,
295 SETTINGS_ROOT, SETTINGS_MATCH);
296
297 auto macObjectInfo = ipmi::getDbusObject(bus, MAC_INTERFACE,
298 SETTINGS_ROOT, SETTINGS_MATCH);
299
300 properties = ipmi::getAllDbusProperties(bus, ipObjectInfo.second,
301 ipObjectInfo.first, IP_INTERFACE);
Ratan Guptacc8feb42017-07-25 21:52:10 +0530302 auto variant =
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530303 ipmi::getDbusProperty(bus, macObjectInfo.second,
304 macObjectInfo.first,
Ratan Guptacc8feb42017-07-25 21:52:10 +0530305 MAC_INTERFACE, "MACAddress");
Ratan Guptadcb10672017-07-10 10:33:50 +0530306
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530307 auto ipAddress = properties["Address"].get<std::string>();
Ratan Guptad70f4532017-08-04 02:07:31 +0530308
309 auto gateway = properties["Gateway"].get<std::string>();
310
311 auto prefix = properties["PrefixLength"].get<uint8_t>();
312
313 uint8_t isStatic = (properties["Origin"].get<std::string>() ==
314 "xyz.openbmc_project.Network.IP.AddressOrigin.Static")
315 ? 1 : 0;
316
Ratan Guptacc8feb42017-07-25 21:52:10 +0530317 auto MACAddress = variant.get<std::string>();
318
Ratan Guptad70f4532017-08-04 02:07:31 +0530319 // it is expected here that we should get the valid data
320 // but we may also get the default values.
321 // Validation of the data is done by settings.
322 //
323 // if mac address is default mac address then
324 // don't send blank override.
Ratan Gupta8c31d232017-08-13 05:49:43 +0530325 if ((MACAddress == ipmi::network::DEFAULT_MAC_ADDRESS))
Ratan Guptad70f4532017-08-04 02:07:31 +0530326 {
327 memset(respptr->data, 0, SIZE_BOOT_OPTION);
328 rc = -1;
329 return rc;
330 }
331 // if addr is static then ipaddress,gateway,prefix
332 // should not be default one,don't send blank override.
333 if (isStatic)
334 {
Ratan Gupta8c31d232017-08-13 05:49:43 +0530335 if((ipAddress == ipmi::network::DEFAULT_ADDRESS) ||
336 (gateway == ipmi::network::DEFAULT_ADDRESS) ||
Ratan Guptad70f4532017-08-04 02:07:31 +0530337 (!prefix))
338 {
339 memset(respptr->data, 0, SIZE_BOOT_OPTION);
340 rc = -1;
341 return rc;
342 }
343 }
344
Ratan Gupta8c31d232017-08-13 05:49:43 +0530345 sscanf(MACAddress.c_str(), ipmi::network::MAC_ADDRESS_FORMAT,
Ratan Guptadcb10672017-07-10 10:33:50 +0530346 (respptr->data + MAC_OFFSET),
347 (respptr->data + MAC_OFFSET + 1),
348 (respptr->data + MAC_OFFSET + 2),
349 (respptr->data + MAC_OFFSET + 3),
350 (respptr->data + MAC_OFFSET + 4),
351 (respptr->data + MAC_OFFSET + 5));
352
Ratan Guptadcb10672017-07-10 10:33:50 +0530353 respptr->data[MAC_OFFSET + 6] = 0x00;
354
Ratan Guptad70f4532017-08-04 02:07:31 +0530355 memcpy(respptr->data + ADDRTYPE_OFFSET, &isStatic,
356 sizeof(isStatic));
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530357
358 uint8_t addressFamily = (properties["Type"].get<std::string>() ==
359 "xyz.openbmc_project.Network.IP.Protocol.IPv4") ?
360 AF_INET : AF_INET6;
361
Ratan Gupta8c31d232017-08-13 05:49:43 +0530362 addrSize = (addressFamily == AF_INET) ?
363 ipmi::network::IPV4_ADDRESS_SIZE_BYTE :
364 ipmi::network::IPV6_ADDRESS_SIZE_BYTE;
Ratan Guptadcb10672017-07-10 10:33:50 +0530365
366 // ipaddress and gateway would be in IPv4 format
Ratan Guptad70f4532017-08-04 02:07:31 +0530367 inet_pton(addressFamily, ipAddress.c_str(),
368 (respptr->data + IPADDR_OFFSET));
Ratan Guptadcb10672017-07-10 10:33:50 +0530369
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530370 uint8_t prefixOffset = IPADDR_OFFSET + addrSize;
371
372 memcpy(respptr->data + prefixOffset, &prefix, sizeof(prefix));
373
374 uint8_t gatewayOffset = prefixOffset + sizeof(decltype(prefix));
375
Ratan Guptad70f4532017-08-04 02:07:31 +0530376 inet_pton(addressFamily, gateway.c_str(),
377 (respptr->data + gatewayOffset));
Ratan Guptadcb10672017-07-10 10:33:50 +0530378
379 }
380 catch (InternalFailure& e)
381 {
382 commit<InternalFailure>();
383 memset(respptr->data, 0, SIZE_BOOT_OPTION);
384 rc = -1;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500385 return rc;
386 }
387
Ratan Guptadcb10672017-07-10 10:33:50 +0530388 //PetiBoot-Specific
Gunnar Mills8991dd62017-10-25 17:11:29 -0500389 //If success then copy the first 9 bytes to the data
Ratan Guptadcb10672017-07-10 10:33:50 +0530390 memcpy(respptr->data, net_conf_initial_bytes,
391 sizeof(net_conf_initial_bytes));
Ratan Guptafd28dd72016-08-01 04:58:01 -0500392
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530393 memcpy(respptr->data + ADDR_SIZE_OFFSET, &addrSize, sizeof(addrSize));
394
Ratan Guptafd28dd72016-08-01 04:58:01 -0500395#ifdef _IPMI_DEBUG_
Ratan Guptadcb10672017-07-10 10:33:50 +0530396 printf("\n===Printing the IPMI Formatted Data========\n");
Ratan Guptafd28dd72016-08-01 04:58:01 -0500397
Ratan Guptadcb10672017-07-10 10:33:50 +0530398 for (uint8_t pos = 0; pos < index; pos++)
399 {
400 printf("%02x ", respptr->data[pos]);
401 }
Ratan Guptafd28dd72016-08-01 04:58:01 -0500402#endif
403
Ratan Guptafd28dd72016-08-01 04:58:01 -0500404 return rc;
405}
406
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530407/** @brief convert IPv4 and IPv6 addresses from binary to text form.
408 * @param[in] family - IPv4/Ipv6
409 * @param[in] data - req data pointer.
410 * @param[in] offset - offset in the data.
411 * @param[in] addrSize - size of the data which needs to be read from offset.
412 * @returns address in text form.
413 */
414
415std::string getAddrStr(uint8_t family, uint8_t* data,
416 uint8_t offset, uint8_t addrSize)
417{
418 char ipAddr[INET6_ADDRSTRLEN] = {};
419
420 switch(family)
421 {
422 case AF_INET:
423 {
424 struct sockaddr_in addr4 {};
425 memcpy(&addr4.sin_addr.s_addr, &data[offset], addrSize);
426
427 inet_ntop(AF_INET, &addr4.sin_addr,
428 ipAddr, INET_ADDRSTRLEN);
429
430 break;
431 }
432 case AF_INET6:
433 {
434 struct sockaddr_in6 addr6 {};
435 memcpy(&addr6.sin6_addr.s6_addr, &data[offset], addrSize);
436
437 inet_ntop(AF_INET6, &addr6.sin6_addr,
438 ipAddr, INET6_ADDRSTRLEN);
439
440 break;
441 }
442 default:
443 {
444 return {};
445 }
446 }
447
448 return ipAddr;
449}
450
Ratan Guptadcb10672017-07-10 10:33:50 +0530451int setHostNetworkData(set_sys_boot_options_t* reqptr)
Ratan Guptafd28dd72016-08-01 04:58:01 -0500452{
Ratan Guptadcb10672017-07-10 10:33:50 +0530453 using namespace std::string_literals;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500454 std::string host_network_config;
Ratan Guptad70f4532017-08-04 02:07:31 +0530455 char mac[] {"00:00:00:00:00:00"};
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530456 std::string ipAddress, gateway;
457 char addrOrigin {0};
458 uint8_t addrSize {0};
Ratan Guptadcb10672017-07-10 10:33:50 +0530459 std::string addressOrigin =
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530460 "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP";
461 std::string addressType =
462 "xyz.openbmc_project.Network.IP.Protocol.IPv4";
Ratan Guptadcb10672017-07-10 10:33:50 +0530463 uint8_t prefix {0};
464 uint32_t zeroCookie = 0;
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530465 uint8_t family = AF_INET;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500466
467 //cookie starts from second byte
468 // version starts from sixth byte
469
Ratan Guptadcb10672017-07-10 10:33:50 +0530470 try
Ratan Guptafd28dd72016-08-01 04:58:01 -0500471 {
Ratan Guptadcb10672017-07-10 10:33:50 +0530472 do
473 {
474 // cookie == 0x21 0x70 0x62 0x21
475 if (memcmp(&(reqptr->data[COOKIE_OFFSET]),
476 (net_conf_initial_bytes + COOKIE_OFFSET),
477 SIZE_COOKIE) != 0)
478 {
479 //cookie == 0
480 if (memcmp(&(reqptr->data[COOKIE_OFFSET]),
481 &zeroCookie,
482 SIZE_COOKIE) == 0)
483 {
484 // need to zero out the network settings.
485 break;
486 }
487
488 log<level::ERR>("Invalid Cookie");
489 elog<InternalFailure>();
490 }
491
492 // vesion == 0x00 0x01
493 if (memcmp(&(reqptr->data[VERSION_OFFSET]),
494 (net_conf_initial_bytes + VERSION_OFFSET),
495 SIZE_VERSION) != 0)
496 {
497
498 log<level::ERR>("Invalid Version");
499 elog<InternalFailure>();
500 }
501
Ratan Gupta8c31d232017-08-13 05:49:43 +0530502 snprintf(mac, SIZE_MAC, ipmi::network::MAC_ADDRESS_FORMAT,
Ratan Guptadcb10672017-07-10 10:33:50 +0530503 reqptr->data[MAC_OFFSET],
504 reqptr->data[MAC_OFFSET + 1],
505 reqptr->data[MAC_OFFSET + 2],
506 reqptr->data[MAC_OFFSET + 3],
507 reqptr->data[MAC_OFFSET + 4],
508 reqptr->data[MAC_OFFSET + 5]);
509
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530510 memcpy(&addrOrigin, &(reqptr->data[ADDRTYPE_OFFSET]),
511 sizeof(decltype(addrOrigin)));
Ratan Guptadcb10672017-07-10 10:33:50 +0530512
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530513 if (addrOrigin)
Ratan Guptadcb10672017-07-10 10:33:50 +0530514 {
515 addressOrigin =
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530516 "xyz.openbmc_project.Network.IP.AddressOrigin.Static";
Ratan Guptadcb10672017-07-10 10:33:50 +0530517 }
518
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530519 // Get the address size
520 memcpy(&addrSize ,&reqptr->data[ADDR_SIZE_OFFSET], sizeof(addrSize));
Ratan Guptadcb10672017-07-10 10:33:50 +0530521
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530522 uint8_t prefixOffset = IPADDR_OFFSET + addrSize;
Ratan Guptadcb10672017-07-10 10:33:50 +0530523
Ratan Guptad70f4532017-08-04 02:07:31 +0530524 memcpy(&prefix, &(reqptr->data[prefixOffset]),
525 sizeof(decltype(prefix)));
Ratan Guptadcb10672017-07-10 10:33:50 +0530526
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530527 uint8_t gatewayOffset = prefixOffset + sizeof(decltype(prefix));
528
Ratan Gupta8c31d232017-08-13 05:49:43 +0530529 if (addrSize != ipmi::network::IPV4_ADDRESS_SIZE_BYTE)
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530530 {
531 addressType = "xyz.openbmc_project.Network.IP.Protocol.IPv6";
532 family = AF_INET6;
533 }
534
535 ipAddress = getAddrStr(family, reqptr->data, IPADDR_OFFSET, addrSize);
Ratan Guptad70f4532017-08-04 02:07:31 +0530536
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530537 gateway = getAddrStr(family, reqptr->data, gatewayOffset, addrSize);
538
Ratan Guptadcb10672017-07-10 10:33:50 +0530539 } while(0);
540
Ratan Guptafd28dd72016-08-01 04:58:01 -0500541 //Cookie == 0 or it is a valid cookie
Ratan Guptadcb10672017-07-10 10:33:50 +0530542 host_network_config += "ipaddress="s + ipAddress +
543 ",prefix="s + std::to_string(prefix) + ",gateway="s + gateway +
544 ",mac="s + mac + ",addressOrigin="s + addressOrigin;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500545
Ratan Guptafd28dd72016-08-01 04:58:01 -0500546
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530547 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
548
549 auto ipObjectInfo = ipmi::getDbusObject(bus, IP_INTERFACE,
550 SETTINGS_ROOT, SETTINGS_MATCH);
551 auto macObjectInfo = ipmi::getDbusObject(bus, MAC_INTERFACE,
552 SETTINGS_ROOT, SETTINGS_MATCH);
Ratan Guptadcb10672017-07-10 10:33:50 +0530553 // set the dbus property
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530554 ipmi::setDbusProperty(bus, ipObjectInfo.second, ipObjectInfo.first,
Ratan Guptadcb10672017-07-10 10:33:50 +0530555 IP_INTERFACE, "Address", std::string(ipAddress));
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530556 ipmi::setDbusProperty(bus, ipObjectInfo.second, ipObjectInfo.first,
Ratan Guptadcb10672017-07-10 10:33:50 +0530557 IP_INTERFACE, "PrefixLength", prefix);
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530558 ipmi::setDbusProperty(bus, ipObjectInfo.second, ipObjectInfo.first,
Ratan Guptadcb10672017-07-10 10:33:50 +0530559 IP_INTERFACE, "Origin", addressOrigin);
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530560 ipmi::setDbusProperty(bus, ipObjectInfo.second, ipObjectInfo.first,
Ratan Guptadcb10672017-07-10 10:33:50 +0530561 IP_INTERFACE, "Gateway", std::string(gateway));
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530562 ipmi::setDbusProperty(bus, ipObjectInfo.second, ipObjectInfo.first,
Ratan Guptadcb10672017-07-10 10:33:50 +0530563 IP_INTERFACE, "Type",
564 std::string("xyz.openbmc_project.Network.IP.Protocol.IPv4"));
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530565 ipmi::setDbusProperty(bus, macObjectInfo.second, macObjectInfo.first,
Ratan Guptadcb10672017-07-10 10:33:50 +0530566 MAC_INTERFACE,"MACAddress", std::string(mac));
Ratan Guptafd28dd72016-08-01 04:58:01 -0500567
Ratan Guptad70f4532017-08-04 02:07:31 +0530568 log<level::DEBUG>("Network configuration changed",
569 entry("NETWORKCONFIG=%s", host_network_config.c_str()));
570
Ratan Guptafd28dd72016-08-01 04:58:01 -0500571 }
Ratan Guptadcb10672017-07-10 10:33:50 +0530572 catch (InternalFailure& e)
573 {
574 commit<InternalFailure>();
575 return -1;
576 }
577
578 return 0;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500579}
580
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500581ipmi_ret_t ipmi_chassis_wildcard(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
582 ipmi_request_t request,
583 ipmi_response_t response,
584 ipmi_data_len_t data_len,
585 ipmi_context_t context)
Adriana Kobylak40814c62015-10-27 15:58:44 -0500586{
587 printf("Handling CHASSIS WILDCARD Netfn:[0x%X], Cmd:[0x%X]\n",netfn, cmd);
588 // Status code.
Nan Li70aa8d92016-08-29 00:11:10 +0800589 ipmi_ret_t rc = IPMI_CC_INVALID;
Adriana Kobylak40814c62015-10-27 15:58:44 -0500590 *data_len = 0;
591 return rc;
592}
593
Nan Li8d15fb42016-08-16 22:29:40 +0800594ipmi_ret_t ipmi_get_chassis_cap(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500595 ipmi_request_t request, ipmi_response_t response,
596 ipmi_data_len_t data_len, ipmi_context_t context)
Nan Li8d15fb42016-08-16 22:29:40 +0800597{
598 // sd_bus error
599 ipmi_ret_t rc = IPMI_CC_OK;
600
601 ipmi_chassis_cap_t chassis_cap{};
602
603 *data_len = sizeof(ipmi_chassis_cap_t);
604
605 // TODO: need future work. Get those flag from MRW.
606
607 // capabilities flags
608 // [7..4] - reserved
609 // [3] – 1b = provides power interlock (IPM 1.5)
610 // [2] – 1b = provides Diagnostic Interrupt (FP NMI)
611 // [1] – 1b = provides “Front Panel Lockout” (indicates that the chassis has capabilities
612 // to lock out external power control and reset button or front panel interfaces
613 // and/or detect tampering with those interfaces).
614 // [0] -1b = Chassis provides intrusion (physical security) sensor.
615 // set to default value 0x0.
616 chassis_cap.cap_flags = 0x0;
617
618 // Since we do not have a separate SDR Device/SEL Device/ FRU repository.
619 // The 20h was given as those 5 device addresses.
620 // Chassis FRU info Device Address
621 chassis_cap.fru_info_dev_addr = 0x20;
622
623 // Chassis SDR Device Address
624 chassis_cap.sdr_dev_addr = 0x20;
625
626 // Chassis SEL Device Address
627 chassis_cap.sel_dev_addr = 0x20;
628
629 // Chassis System Management Device Address
630 chassis_cap.system_management_dev_addr = 0x20;
631
632 // Chassis Bridge Device Address.
633 chassis_cap.bridge_dev_addr = 0x20;
634
635 memcpy(response, &chassis_cap, *data_len);
636
637 return rc;
638}
639
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530640//------------------------------------------
641// Calls into Host State Manager Dbus object
642//------------------------------------------
643int initiate_state_transition(State::Host::Transition transition)
vishwa36993272015-11-20 12:43:49 -0600644{
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500645 // OpenBMC Host State Manager dbus framework
646 constexpr auto HOST_STATE_MANAGER_ROOT = "/xyz/openbmc_project/state/host0";
647 constexpr auto HOST_STATE_MANAGER_IFACE = "xyz.openbmc_project.State.Host";
648 constexpr auto DBUS_PROPERTY_IFACE = "org.freedesktop.DBus.Properties";
649 constexpr auto PROPERTY = "RequestedHostTransition";
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530650
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500651 // sd_bus error
652 int rc = 0;
653 char *busname = NULL;
vishwa36993272015-11-20 12:43:49 -0600654
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500655 // SD Bus error report mechanism.
656 sd_bus_error bus_error = SD_BUS_ERROR_NULL;
vishwa36993272015-11-20 12:43:49 -0600657
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500658 // Gets a hook onto either a SYSTEM or SESSION bus
659 sd_bus *bus_type = ipmid_get_sd_bus_connection();
660 rc = mapper_get_service(bus_type, HOST_STATE_MANAGER_ROOT, &busname);
661 if (rc < 0)
662 {
663 log<level::ERR>("Failed to get bus name",
664 entry("ERROR=%s, OBJPATH=%s",
665 strerror(-rc), HOST_STATE_MANAGER_ROOT));
666 return rc;
667 }
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530668
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500669 // Convert to string equivalent of the passed in transition enum.
670 auto request = State::convertForMessage(transition);
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530671
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500672 rc = sd_bus_call_method(bus_type, // On the system bus
673 busname, // Service to contact
674 HOST_STATE_MANAGER_ROOT, // Object path
675 DBUS_PROPERTY_IFACE, // Interface name
676 "Set", // Method to be called
677 &bus_error, // object to return error
678 nullptr, // Response buffer if any
679 "ssv", // Takes 3 arguments
680 HOST_STATE_MANAGER_IFACE,
681 PROPERTY,
682 "s", request.c_str());
683 if(rc < 0)
684 {
685 log<level::ERR>("Failed to initiate transition",
686 entry("ERROR=%s, REQUEST=%s",
687 bus_error.message, request.c_str()));
688 }
689 else
690 {
691 log<level::INFO>("Transition request initiated successfully");
692 }
vishwa36993272015-11-20 12:43:49 -0600693
694 sd_bus_error_free(&bus_error);
Sergey Solomineb9b8142016-08-23 09:07:28 -0500695 free(busname);
vishwa36993272015-11-20 12:43:49 -0600696
Sergey Solomineb9b8142016-08-23 09:07:28 -0500697 return rc;
vishwa36993272015-11-20 12:43:49 -0600698}
699
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500700namespace power_policy
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500701{
Nan Lifdd8ec52016-08-28 03:57:40 +0800702
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500703using namespace sdbusplus::xyz::openbmc_project::Control::Power::server;
704using IpmiValue = uint8_t;
705using DbusValue = RestorePolicy::Policy;
Nan Lifdd8ec52016-08-28 03:57:40 +0800706
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500707std::map<DbusValue, IpmiValue> dbusToIpmi =
708{
709 {RestorePolicy::Policy::AlwaysOff, 0x00},
710 {RestorePolicy::Policy::Restore, 0x01},
711 {RestorePolicy::Policy::AlwaysOn, 0x02}
712};
Nan Lifdd8ec52016-08-28 03:57:40 +0800713
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500714} // namespace power_policy
Nan Lifdd8ec52016-08-28 03:57:40 +0800715
716//----------------------------------------------------------------------
717// Get Chassis Status commands
718//----------------------------------------------------------------------
719ipmi_ret_t ipmi_get_chassis_status(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500720 ipmi_request_t request,
721 ipmi_response_t response,
722 ipmi_data_len_t data_len,
723 ipmi_context_t context)
Nan Lifdd8ec52016-08-28 03:57:40 +0800724{
725 const char *objname = "/org/openbmc/control/power0";
726 const char *intf = "org.openbmc.control.Power";
727
728 sd_bus *bus = NULL;
729 sd_bus_message *reply = NULL;
730 int r = 0;
731 int pgood = 0;
732 char *busname = NULL;
733 ipmi_ret_t rc = IPMI_CC_OK;
734 ipmi_get_chassis_status_t chassis_status{};
735
Nan Lifdd8ec52016-08-28 03:57:40 +0800736 uint8_t s = 0;
737
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500738 using namespace chassis::internal;
739 using namespace chassis::internal::cache;
740 using namespace power_policy;
741
Deepak Kodihallie6027092017-08-27 08:13:37 -0500742 const auto& powerRestoreSetting = objects.map.at(powerRestoreIntf).front();
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500743 auto method =
744 dbus.new_method_call(
745 objects.service(powerRestoreSetting, powerRestoreIntf).c_str(),
746 powerRestoreSetting.c_str(),
Ratan Guptacc8feb42017-07-25 21:52:10 +0530747 ipmi::PROP_INTF,
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500748 "Get");
749 method.append(powerRestoreIntf, "PowerRestorePolicy");
750 auto resp = dbus.call(method);
751 if (resp.is_method_error())
752 {
753 log<level::ERR>("Error in PowerRestorePolicy Get");
754 report<InternalFailure>();
755 *data_len = 0;
756 return IPMI_CC_UNSPECIFIED_ERROR;
757 }
758 sdbusplus::message::variant<std::string> result;
759 resp.read(result);
760 auto powerRestore =
761 RestorePolicy::convertPolicyFromString(result.get<std::string>());
Nan Lifdd8ec52016-08-28 03:57:40 +0800762
763 *data_len = 4;
764
Tom Joseph63a00512017-08-09 23:39:59 +0530765 bus = ipmid_get_sd_bus_connection();
766
Nan Lifdd8ec52016-08-28 03:57:40 +0800767 r = mapper_get_service(bus, objname, &busname);
768 if (r < 0) {
769 fprintf(stderr, "Failed to get bus name, return value: %s.\n", strerror(-r));
770 rc = IPMI_CC_UNSPECIFIED_ERROR;
771 goto finish;
772 }
773
774 r = sd_bus_get_property(bus, busname, objname, intf, "pgood", NULL, &reply, "i");
775 if (r < 0) {
776 fprintf(stderr, "Failed to call sd_bus_get_property:%d, %s\n", r, strerror(-r));
777 fprintf(stderr, "Bus: %s, Path: %s, Interface: %s\n",
778 busname, objname, intf);
779 rc = IPMI_CC_UNSPECIFIED_ERROR;
780 goto finish;
781 }
782
783 r = sd_bus_message_read(reply, "i", &pgood);
784 if (r < 0) {
785 fprintf(stderr, "Failed to read sensor: %s\n", strerror(-r));
786 rc = IPMI_CC_UNSPECIFIED_ERROR;
787 goto finish;
788 }
789
790 printf("pgood is 0x%02x\n", pgood);
791
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500792 s = dbusToIpmi.at(powerRestore);
Nan Lifdd8ec52016-08-28 03:57:40 +0800793
794 // Current Power State
795 // [7] reserved
796 // [6..5] power restore policy
797 // 00b = chassis stays powered off after AC/mains returns
798 // 01b = after AC returns, power is restored to the state that was
799 // in effect when AC/mains was lost.
800 // 10b = chassis always powers up after AC/mains returns
801 // 11b = unknow
802 // Set to 00b, by observing the hardware behavior.
803 // Do we need to define a dbus property to identify the restore policy?
804
805 // [4] power control fault
806 // 1b = controller attempted to turn system power on or off, but
807 // system did not enter desired state.
808 // Set to 0b, since We don't support it..
809
810 // [3] power fault
811 // 1b = fault detected in main power subsystem.
812 // set to 0b. for we don't support it.
813
814 // [2] 1b = interlock (chassis is presently shut down because a chassis
815 // panel interlock switch is active). (IPMI 1.5)
816 // set to 0b, for we don't support it.
817
818 // [1] power overload
819 // 1b = system shutdown because of power overload condition.
820 // set to 0b, for we don't support it.
821
822 // [0] power is on
823 // 1b = system power is on
824 // 0b = system power is off(soft-off S4/S5, or mechanical off)
825
826 chassis_status.cur_power_state = ((s & 0x3)<<5) | (pgood & 0x1);
827
828 // Last Power Event
829 // [7..5] – reserved
830 // [4] – 1b = last ‘Power is on’ state was entered via IPMI command
831 // [3] – 1b = last power down caused by power fault
832 // [2] – 1b = last power down caused by a power interlock being activated
833 // [1] – 1b = last power down caused by a Power overload
834 // [0] – 1b = AC failed
835 // set to 0x0, for we don't support these fields.
836
837 chassis_status.last_power_event = 0;
838
839 // Misc. Chassis State
840 // [7] – reserved
841 // [6] – 1b = Chassis Identify command and state info supported (Optional)
842 // 0b = Chassis Identify command support unspecified via this command.
843 // (The Get Command Support command , if implemented, would still
844 // indicate support for the Chassis Identify command)
845 // [5..4] – Chassis Identify State. Mandatory when bit[6] =1b, reserved (return
846 // as 00b) otherwise. Returns the present chassis identify state.
847 // Refer to the Chassis Identify command for more info.
848 // 00b = chassis identify state = Off
849 // 01b = chassis identify state = Temporary(timed) On
850 // 10b = chassis identify state = Indefinite On
851 // 11b = reserved
852 // [3] – 1b = Cooling/fan fault detected
853 // [2] – 1b = Drive Fault
854 // [1] – 1b = Front Panel Lockout active (power off and reset via chassis
855 // push-buttons disabled.)
856 // [0] – 1b = Chassis Intrusion active
857 // set to 0, for we don't support them.
858 chassis_status.misc_power_state = 0;
859
860 // Front Panel Button Capabilities and disable/enable status(Optional)
861 // set to 0, for we don't support them.
862 chassis_status.front_panel_button_cap_status = 0;
863
864 // Pack the actual response
865 memcpy(response, &chassis_status, *data_len);
866
867finish:
868 free(busname);
869 reply = sd_bus_message_unref(reply);
870
871 return rc;
872}
Chris Austen7888c4d2015-12-03 15:26:20 -0600873
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +0530874//-------------------------------------------------------------
875// Send a command to SoftPowerOff application to stop any timer
876//-------------------------------------------------------------
877int stop_soft_off_timer()
878{
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +0530879 constexpr auto iface = "org.freedesktop.DBus.Properties";
880 constexpr auto soft_off_iface = "xyz.openbmc_project.Ipmi.Internal."
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500881 "SoftPowerOff";
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +0530882
883 constexpr auto property = "ResponseReceived";
884 constexpr auto value = "xyz.openbmc_project.Ipmi.Internal."
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500885 "SoftPowerOff.HostResponse.HostShutdown";
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +0530886
887 // Get the system bus where most system services are provided.
888 auto bus = ipmid_get_sd_bus_connection();
889
890 // Get the service name
Andrew Geissler2b4e4592017-06-08 11:18:35 -0500891 // TODO openbmc/openbmc#1661 - Mapper refactor
892 //
893 // See openbmc/openbmc#1743 for some details but high level summary is that
894 // for now the code will directly call the soft off interface due to a
895 // race condition with mapper usage
896 //
897 //char *busname = nullptr;
898 //auto r = mapper_get_service(bus, SOFTOFF_OBJPATH, &busname);
899 //if (r < 0)
900 //{
901 // fprintf(stderr, "Failed to get %s bus name: %s\n",
902 // SOFTOFF_OBJPATH, strerror(-r));
903 // return r;
904 //}
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +0530905
906 // No error object or reply expected.
Andrew Geissler2b4e4592017-06-08 11:18:35 -0500907 int rc = sd_bus_call_method(bus, SOFTOFF_BUSNAME, SOFTOFF_OBJPATH, iface,
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500908 "Set", nullptr, nullptr, "ssv",
909 soft_off_iface, property, "s", value);
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +0530910 if (rc < 0)
911 {
912 fprintf(stderr, "Failed to set property in SoftPowerOff object: %s\n",
913 strerror(-rc));
914 }
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500915
Andrew Geissler2b4e4592017-06-08 11:18:35 -0500916 //TODO openbmc/openbmc#1661 - Mapper refactor
917 //free(busname);
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +0530918 return rc;
919}
920
vishwa36993272015-11-20 12:43:49 -0600921//----------------------------------------------------------------------
Andrew Geisslera6e3a302017-05-31 19:34:00 -0500922// Create file to indicate there is no need for softoff notification to host
923//----------------------------------------------------------------------
924void indicate_no_softoff_needed()
925{
926 fs::path path{HOST_INBAND_REQUEST_DIR};
927 if (!fs::is_directory(path))
928 {
929 fs::create_directory(path);
930 }
931
932 // Add the host instance (default 0 for now) to the file name
933 std::string file{HOST_INBAND_REQUEST_FILE};
934 auto size = std::snprintf(nullptr,0,file.c_str(),0);
935 size++; // null
936 std::unique_ptr<char[]> buf(new char[size]);
937 std::snprintf(buf.get(),size,file.c_str(),0);
938
939 // Append file name to directory and create it
940 path /= buf.get();
941 std::ofstream(path.c_str());
942}
943
944//----------------------------------------------------------------------
vishwa36993272015-11-20 12:43:49 -0600945// Chassis Control commands
946//----------------------------------------------------------------------
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500947ipmi_ret_t ipmi_chassis_control(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
948 ipmi_request_t request,
949 ipmi_response_t response,
950 ipmi_data_len_t data_len,
951 ipmi_context_t context)
vishwa36993272015-11-20 12:43:49 -0600952{
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500953 // Error from power off.
954 int rc = 0;
vishwa36993272015-11-20 12:43:49 -0600955
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500956 // No response for this command.
vishwa36993272015-11-20 12:43:49 -0600957 *data_len = 0;
958
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500959 // Catch the actual operaton by peeking into request buffer
960 uint8_t chassis_ctrl_cmd = *(uint8_t *)request;
961 printf("Chassis Control Command: Operation:[0x%X]\n",chassis_ctrl_cmd);
vishwa36993272015-11-20 12:43:49 -0600962
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500963 switch(chassis_ctrl_cmd)
964 {
965 case CMD_POWER_ON:
966 rc = initiate_state_transition(State::Host::Transition::On);
967 break;
968 case CMD_POWER_OFF:
Vishwanatha Subbanna8b26d352017-08-04 18:35:18 +0530969 // This path would be hit in 2 conditions.
970 // 1: When user asks for power off using ipmi chassis command 0x04
971 // 2: Host asking for power off post shutting down.
972
973 // If it's a host requested power off, then need to nudge Softoff
974 // application that it needs to stop the watchdog timer if running.
975 // If it is a user requested power off, then this is not really
976 // needed. But then we need to differentiate between user and host
977 // calling this same command
978
979 // For now, we are going ahead with trying to nudge the soft off and
980 // interpret the failure to do so as a non softoff case
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500981 rc = stop_soft_off_timer();
Vishwanatha Subbanna8b26d352017-08-04 18:35:18 +0530982
Andrew Geisslera6e3a302017-05-31 19:34:00 -0500983 // Only request the Off transition if the soft power off
984 // application is not running
985 if (rc < 0)
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500986 {
Andrew Geisslera6e3a302017-05-31 19:34:00 -0500987 // First create a file to indicate to the soft off application
Vishwanatha Subbanna8b26d352017-08-04 18:35:18 +0530988 // that it should not run. Not doing this will result in State
989 // manager doing a default soft power off when asked for power
990 // off.
Andrew Geisslera6e3a302017-05-31 19:34:00 -0500991 indicate_no_softoff_needed();
992
993 // Now request the shutdown
994 rc = initiate_state_transition(State::Host::Transition::Off);
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500995 }
Andrew Geisslera6e3a302017-05-31 19:34:00 -0500996 else
997 {
Vishwanatha Subbanna8b26d352017-08-04 18:35:18 +0530998 log<level::INFO>("Soft off is running, so let shutdown target "
999 "stop the host");
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001000 }
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001001 break;
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +05301002
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001003 case CMD_HARD_RESET:
1004 case CMD_POWER_CYCLE:
1005 // SPEC has a section that says certain implementations can trigger
1006 // PowerOn if power is Off when a command to power cycle is
1007 // requested
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001008
1009 // First create a file to indicate to the soft off application
1010 // that it should not run since this is a direct user initiated
1011 // power reboot request (i.e. a reboot request that is not
1012 // originating via a soft power off SMS request)
1013 indicate_no_softoff_needed();
1014
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001015 rc = initiate_state_transition(State::Host::Transition::Reboot);
1016 break;
Vishwanatha Subbanna8b26d352017-08-04 18:35:18 +05301017
1018 case CMD_SOFT_OFF_VIA_OVER_TEMP:
1019 // Request Host State Manager to do a soft power off
1020 rc = initiate_state_transition(State::Host::Transition::Off);
1021 break;
1022
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001023 default:
1024 {
1025 fprintf(stderr, "Invalid Chassis Control command:[0x%X] received\n",chassis_ctrl_cmd);
1026 rc = -1;
1027 }
1028 }
vishwa36993272015-11-20 12:43:49 -06001029
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001030 return ( (rc < 0) ? IPMI_CC_INVALID : IPMI_CC_OK);
vishwa36993272015-11-20 12:43:49 -06001031}
1032
James Feist5bfbde32017-11-22 13:40:53 -08001033ipmi_ret_t ipmi_chassis_identify(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1034 ipmi_request_t request,
1035 ipmi_response_t response,
1036 ipmi_data_len_t data_len,
1037 ipmi_context_t context)
1038{
1039 static std::atomic_size_t currentCallerId(0);
1040 static std::unique_ptr<std::future<void>> future;
1041 static std::condition_variable condition;
1042 static std::mutex timeoutMutex;
1043
1044 if (*data_len > 2)
1045 {
1046 return IPMI_CC_REQ_DATA_LEN_INVALID;
1047 }
1048 uint8_t identifyInterval = *data_len > 0 ?
1049 (static_cast<uint8_t*>(request))[0] :
1050 DEFAULT_IDENTIFY_TIME_OUT;
1051 bool forceIdentify =
1052 *data_len == 2 ? (static_cast<uint8_t*>(request))[1] & 0x01 : false;
1053
1054 currentCallerId++;
1055
1056 // stop any threads currently running
1057 condition.notify_all();
1058
1059 // lookup enclosure_identify group owner(s) in mapper
1060 auto mapperCall = chassis::internal::dbus.new_method_call(
1061 ipmi::MAPPER_BUS_NAME,
1062 ipmi::MAPPER_OBJ,
1063 ipmi::MAPPER_INTF,
1064 "GetObject");
1065
1066 mapperCall.append(identify_led_object_name);
1067 static const std::vector<std::string> interfaces =
1068 {
1069 "xyz.openbmc_project.Led.Group"
1070 };
1071 mapperCall.append(interfaces);
1072 auto mapperReply = chassis::internal::dbus.call(mapperCall);
1073 if (mapperReply.is_method_error())
1074 {
1075 log<level::ERR>("Chassis Identify: Error communicating to mapper.");
1076 return IPMI_CC_RESPONSE_ERROR;
1077 }
1078 std::vector<std::pair<std::string, std::vector<std::string>>> mapperResp;
1079 mapperReply.read(mapperResp);
1080
1081 for (auto& object : mapperResp)
1082 {
1083 std::string& connection = object.first;
1084
1085 if (identifyInterval || forceIdentify)
1086 {
1087 auto ledOn = chassis::internal::dbus.new_method_call(
1088 connection.c_str(),
1089 identify_led_object_name,
1090 "org.freedesktop.DBus.Properties", "Set");
1091 ledOn.append(
1092 "xyz.openbmc_project.Led.Group", "Asserted",
1093 sdbusplus::message::variant<bool>(
1094 true));
1095 auto ledReply = chassis::internal::dbus.call(ledOn);
1096 if (ledReply.is_method_error())
1097 {
1098 log<level::ERR>("Chassis Identify: Error Setting State On\n");
1099 return IPMI_CC_RESPONSE_ERROR;
1100 }
1101 if (forceIdentify)
1102 {
1103 return IPMI_CC_OK;
1104 }
1105 }
1106
1107 size_t threadCallerId = currentCallerId;
1108 future = std::make_unique<std::future<void>>(
1109 std::async(std::launch::async,
1110 [connection,
1111 identifyInterval,
1112 threadCallerId]
1113 {
1114 std::unique_lock<std::mutex> lock(timeoutMutex);
1115 if (condition.wait_for(lock,
1116 std::chrono::seconds(identifyInterval),
1117 [&threadCallerId]{return currentCallerId != threadCallerId;}))
1118 {
1119 return; // another thread started.
1120 }
1121 auto ledOff = chassis::internal::dbus.new_method_call(
1122 connection.c_str(),
1123 identify_led_object_name,
1124 "org.freedesktop.DBus.Properties", "Set");
1125 ledOff.append("xyz.openbmc_project.Led.Group", "Asserted",
1126 sdbusplus::message::variant<bool>(
1127 false));
1128 auto ledReply = chassis::internal::dbus.call(ledOff);
1129 if (ledReply.is_method_error())
1130 {
1131 log<level::ERR>("Chassis Identify: Error Setting State Off\n");
1132 }
1133 }));
1134 }
1135 return IPMI_CC_OK;
1136}
1137
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001138namespace boot_options
1139{
1140
1141using namespace sdbusplus::xyz::openbmc_project::Control::Boot::server;
1142using IpmiValue = uint8_t;
1143constexpr auto ipmiDefault = 0;
1144
1145std::map<IpmiValue, Source::Sources> sourceIpmiToDbus =
1146{
1147 {0x01, Source::Sources::Network},
1148 {0x02, Source::Sources::Disk},
1149 {0x05, Source::Sources::ExternalMedia},
1150 {ipmiDefault, Source::Sources::Default}
shgoupfd84fbbf2015-12-17 10:05:51 +08001151};
1152
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001153std::map<IpmiValue, Mode::Modes> modeIpmiToDbus =
1154{
1155 {0x03, Mode::Modes::Safe},
1156 {0x06, Mode::Modes::Setup},
1157 {ipmiDefault, Mode::Modes::Regular}
shgoupfd84fbbf2015-12-17 10:05:51 +08001158};
1159
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001160std::map<Source::Sources, IpmiValue> sourceDbusToIpmi =
1161{
1162 {Source::Sources::Network, 0x01},
1163 {Source::Sources::Disk, 0x02},
1164 {Source::Sources::ExternalMedia, 0x05},
1165 {Source::Sources::Default, ipmiDefault}
1166};
shgoupfd84fbbf2015-12-17 10:05:51 +08001167
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001168std::map<Mode::Modes, IpmiValue> modeDbusToIpmi =
1169{
1170 {Mode::Modes::Safe, 0x03},
1171 {Mode::Modes::Setup, 0x06},
1172 {Mode::Modes::Regular, ipmiDefault}
1173};
shgoupfd84fbbf2015-12-17 10:05:51 +08001174
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001175} // namespace boot_options
shgoupfd84fbbf2015-12-17 10:05:51 +08001176
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001177ipmi_ret_t ipmi_chassis_get_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1178 ipmi_request_t request,
1179 ipmi_response_t response,
1180 ipmi_data_len_t data_len,
1181 ipmi_context_t context)
Adriana Kobylak40814c62015-10-27 15:58:44 -05001182{
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001183 using namespace boot_options;
shgoupfd84fbbf2015-12-17 10:05:51 +08001184 ipmi_ret_t rc = IPMI_CC_PARM_NOT_SUPPORTED;
1185 char *p = NULL;
1186 get_sys_boot_options_response_t *resp = (get_sys_boot_options_response_t *) response;
1187 get_sys_boot_options_t *reqptr = (get_sys_boot_options_t*) request;
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001188 IpmiValue bootOption = ipmiDefault;
Adriana Kobylak40814c62015-10-27 15:58:44 -05001189
1190 printf("IPMI GET_SYS_BOOT_OPTIONS\n");
1191
shgoupfd84fbbf2015-12-17 10:05:51 +08001192 memset(resp,0,sizeof(*resp));
1193 resp->version = SET_PARM_VERSION;
1194 resp->parm = 5;
ratagupta6f6bff2016-04-04 06:20:11 -05001195 resp->data[0] = SET_PARM_BOOT_FLAGS_VALID_ONE_TIME;
Adriana Kobylak40814c62015-10-27 15:58:44 -05001196
Adriana Kobylak40814c62015-10-27 15:58:44 -05001197
shgoupfd84fbbf2015-12-17 10:05:51 +08001198 /*
1199 * Parameter #5 means boot flags. Please refer to 28.13 of ipmi doc.
1200 * This is the only parameter used by petitboot.
1201 */
Ratan Guptafd28dd72016-08-01 04:58:01 -05001202 if ( reqptr->parameter == static_cast<uint8_t>
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001203 ( BootOptionParameter::BOOT_FLAGS )) {
shgoupfd84fbbf2015-12-17 10:05:51 +08001204
Ratan Guptafd28dd72016-08-01 04:58:01 -05001205 *data_len = static_cast<uint8_t>(BootOptionResponseSize::BOOT_FLAGS);
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001206 using namespace chassis::internal;
1207 using namespace chassis::internal::cache;
shgoupfd84fbbf2015-12-17 10:05:51 +08001208
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001209 try
ratagupta6f6bff2016-04-04 06:20:11 -05001210 {
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001211 auto bootSetting = settings::boot::setting(objects, bootSourceIntf);
1212 const auto& bootSourceSetting =
1213 std::get<settings::Path>(bootSetting);
1214 auto oneTimeEnabled =
1215 std::get<settings::boot::OneTimeEnabled>(bootSetting);
1216 auto method =
1217 dbus.new_method_call(
1218 objects.service(bootSourceSetting, bootSourceIntf).c_str(),
1219 bootSourceSetting.c_str(),
1220 ipmi::PROP_INTF,
1221 "Get");
1222 method.append(bootSourceIntf, "BootSource");
1223 auto reply = dbus.call(method);
1224 if (reply.is_method_error())
1225 {
1226 log<level::ERR>("Error in BootSource Get");
1227 report<InternalFailure>();
1228 *data_len = 0;
1229 return IPMI_CC_UNSPECIFIED_ERROR;
1230 }
1231 sdbusplus::message::variant<std::string> result;
1232 reply.read(result);
1233 auto bootSource =
1234 Source::convertSourcesFromString(result.get<std::string>());
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001235
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001236 bootSetting = settings::boot::setting(objects, bootModeIntf);
1237 const auto& bootModeSetting = std::get<settings::Path>(bootSetting);
1238 method = dbus.new_method_call(
1239 objects.service(bootModeSetting, bootModeIntf).
1240 c_str(),
1241 bootModeSetting.c_str(),
1242 ipmi::PROP_INTF,
1243 "Get");
1244 method.append(bootModeIntf, "BootMode");
1245 reply = dbus.call(method);
1246 if (reply.is_method_error())
1247 {
1248 log<level::ERR>("Error in BootMode Get");
1249 report<InternalFailure>();
1250 *data_len = 0;
1251 return IPMI_CC_UNSPECIFIED_ERROR;
1252 }
1253 reply.read(result);
1254 auto bootMode =
1255 Mode::convertModesFromString(result.get<std::string>());
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001256
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001257 bootOption = sourceDbusToIpmi.at(bootSource);
1258 if ((Mode::Modes::Regular == bootMode) &&
1259 (Source::Sources::Default == bootSource))
1260 {
1261 bootOption = ipmiDefault;
1262 }
1263 else if (Source::Sources::Default == bootSource)
1264 {
1265 bootOption = modeDbusToIpmi.at(bootMode);
1266 }
1267 resp->data[1] = (bootOption << 2);
ratagupta6f6bff2016-04-04 06:20:11 -05001268
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001269 resp->data[0] = oneTimeEnabled ?
1270 SET_PARM_BOOT_FLAGS_VALID_ONE_TIME:
1271 SET_PARM_BOOT_FLAGS_VALID_PERMANENT;
ratagupta6f6bff2016-04-04 06:20:11 -05001272
ratagupta6f6bff2016-04-04 06:20:11 -05001273 rc = IPMI_CC_OK;
ratagupta6f6bff2016-04-04 06:20:11 -05001274 }
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001275 catch (InternalFailure& e)
1276 {
1277 report<InternalFailure>();
1278 *data_len = 0;
1279 return IPMI_CC_UNSPECIFIED_ERROR;
1280 }
Ratan Guptafd28dd72016-08-01 04:58:01 -05001281 } else if ( reqptr->parameter == static_cast<uint8_t>
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001282 ( BootOptionParameter::OPAL_NETWORK_SETTINGS )) {
Ratan Guptafd28dd72016-08-01 04:58:01 -05001283
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001284 *data_len = static_cast<uint8_t>(BootOptionResponseSize::OPAL_NETWORK_SETTINGS);
Ratan Guptafd28dd72016-08-01 04:58:01 -05001285
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001286 resp->parm = static_cast<uint8_t>(BootOptionParameter::OPAL_NETWORK_SETTINGS);
Ratan Guptafd28dd72016-08-01 04:58:01 -05001287
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001288 int ret = getHostNetworkData(resp);
Ratan Guptafd28dd72016-08-01 04:58:01 -05001289
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001290 if (ret < 0) {
Ratan Guptafd28dd72016-08-01 04:58:01 -05001291
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001292 fprintf(stderr, "getHostNetworkData failed for get_sys_boot_options.\n");
1293 rc = IPMI_CC_UNSPECIFIED_ERROR;
Ratan Guptafd28dd72016-08-01 04:58:01 -05001294
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001295 }else
1296 rc = IPMI_CC_OK;
Ratan Guptafd28dd72016-08-01 04:58:01 -05001297 }
1298
1299 else {
Adriana Kobylak40814c62015-10-27 15:58:44 -05001300 fprintf(stderr, "Unsupported parameter 0x%x\n", reqptr->parameter);
shgoupfd84fbbf2015-12-17 10:05:51 +08001301 }
1302
1303 if (p)
1304 free(p);
1305
Ratan Guptafd28dd72016-08-01 04:58:01 -05001306 if (rc == IPMI_CC_OK)
1307 {
1308 *data_len += 2;
1309 }
1310
shgoupfd84fbbf2015-12-17 10:05:51 +08001311 return rc;
1312}
1313
1314
1315
1316ipmi_ret_t ipmi_chassis_set_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001317 ipmi_request_t request,
1318 ipmi_response_t response,
1319 ipmi_data_len_t data_len,
1320 ipmi_context_t context)
shgoupfd84fbbf2015-12-17 10:05:51 +08001321{
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001322 using namespace boot_options;
shgoupfd84fbbf2015-12-17 10:05:51 +08001323 ipmi_ret_t rc = IPMI_CC_OK;
shgoupfd84fbbf2015-12-17 10:05:51 +08001324 set_sys_boot_options_t *reqptr = (set_sys_boot_options_t *) request;
1325
Ratan Guptafd28dd72016-08-01 04:58:01 -05001326 printf("IPMI SET_SYS_BOOT_OPTIONS reqptr->parameter =[%d]\n",reqptr->parameter);
1327
shgoupfd84fbbf2015-12-17 10:05:51 +08001328 // This IPMI command does not have any resposne data
1329 *data_len = 0;
1330
1331 /* 000101
1332 * Parameter #5 means boot flags. Please refer to 28.13 of ipmi doc.
1333 * This is the only parameter used by petitboot.
1334 */
Ratan Guptafd28dd72016-08-01 04:58:01 -05001335
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001336 if (reqptr->parameter == (uint8_t)BootOptionParameter::BOOT_FLAGS)
1337 {
1338 IpmiValue bootOption = ((reqptr->data[1] & 0x3C) >> 2);
1339 using namespace chassis::internal;
1340 using namespace chassis::internal::cache;
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001341 auto oneTimeEnabled = false;
1342 constexpr auto enabledIntf = "xyz.openbmc_project.Object.Enable";
Tom Joseph57e8eb72017-09-25 18:05:02 +05301343 constexpr auto oneTimePath =
1344 "/xyz/openbmc_project/control/host0/boot/one_time";
shgoupfd84fbbf2015-12-17 10:05:51 +08001345
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001346 try
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001347 {
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001348 bool permanent =
1349 (reqptr->data[0] & SET_PARM_BOOT_FLAGS_PERMANENT) ==
1350 SET_PARM_BOOT_FLAGS_PERMANENT;
1351
Tom Joseph57e8eb72017-09-25 18:05:02 +05301352 auto bootSetting =
1353 settings::boot::setting(objects, bootSourceIntf);
1354
1355 oneTimeEnabled =
1356 std::get<settings::boot::OneTimeEnabled>(bootSetting);
1357
1358 /*
1359 * Check if the current boot setting is onetime or permanent, if the
1360 * request in the command is otherwise, then set the "Enabled"
1361 * property in one_time object path to 'True' to indicate onetime
1362 * and 'False' to indicate permanent.
1363 *
1364 * Once the onetime/permanent setting is applied, then the bootMode
1365 * and bootSource is updated for the corresponding object.
1366 */
1367 if ((permanent && oneTimeEnabled) ||
1368 (!permanent && !oneTimeEnabled))
1369 {
1370 auto service = ipmi::getService(dbus, enabledIntf, oneTimePath);
1371
1372 ipmi::setDbusProperty(dbus,
1373 service,
1374 oneTimePath,
1375 enabledIntf,
1376 "Enabled",
1377 !permanent);
1378 }
1379
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001380 auto modeItr = modeIpmiToDbus.find(bootOption);
1381 auto sourceItr = sourceIpmiToDbus.find(bootOption);
1382 if (sourceIpmiToDbus.end() != sourceItr)
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001383 {
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001384 sdbusplus::message::variant<std::string> property =
1385 convertForMessage(sourceItr->second);
Tom Joseph57e8eb72017-09-25 18:05:02 +05301386 auto bootSetting = settings::boot::setting(objects,
1387 bootSourceIntf);
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001388 const auto& bootSourceSetting =
1389 std::get<settings::Path>(bootSetting);
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001390 auto method =
1391 dbus.new_method_call(
1392 objects.service(bootSourceSetting, bootSourceIntf).
1393 c_str(),
1394 bootSourceSetting.c_str(),
1395 ipmi::PROP_INTF,
1396 "Set");
1397 method.append(bootSourceIntf, "BootSource", property);
1398 auto reply = dbus.call(method);
1399 if (reply.is_method_error())
1400 {
1401 log<level::ERR>("Error in BootSource Set");
1402 report<InternalFailure>();
1403 *data_len = 0;
1404 return IPMI_CC_UNSPECIFIED_ERROR;
1405 }
1406
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001407 }
1408 if (modeIpmiToDbus.end() != modeItr)
1409 {
1410 sdbusplus::message::variant<std::string> property =
1411 convertForMessage(modeItr->second);
Tom Joseph57e8eb72017-09-25 18:05:02 +05301412 auto bootSetting = settings::boot::setting(objects,
1413 bootModeIntf);
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001414 const auto& bootModeSetting =
1415 std::get<settings::Path>(bootSetting);
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001416 auto method =
1417 dbus.new_method_call(
1418 objects.service(bootModeSetting, bootModeIntf).c_str(),
1419 bootModeSetting.c_str(),
1420 ipmi::PROP_INTF,
1421 "Set");
1422 method.append(bootModeIntf, "BootMode", property);
1423 auto reply = dbus.call(method);
1424 if (reply.is_method_error())
1425 {
1426 log<level::ERR>("Error in BootMode Set");
1427 report<InternalFailure>();
1428 *data_len = 0;
1429 return IPMI_CC_UNSPECIFIED_ERROR;
1430 }
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001431 }
1432 }
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001433 catch (InternalFailure& e)
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001434 {
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001435 report<InternalFailure>();
1436 *data_len = 0;
1437 return IPMI_CC_UNSPECIFIED_ERROR;
shgoupfd84fbbf2015-12-17 10:05:51 +08001438 }
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001439 } else if (reqptr->parameter ==
1440 (uint8_t)BootOptionParameter::OPAL_NETWORK_SETTINGS) {
Ratan Guptafd28dd72016-08-01 04:58:01 -05001441
1442 int ret = setHostNetworkData(reqptr);
1443 if (ret < 0) {
1444 fprintf(stderr, "setHostNetworkData failed for set_sys_boot_options.\n");
1445 rc = IPMI_CC_UNSPECIFIED_ERROR;
1446 }
Tom Josephf536c902017-09-25 18:08:15 +05301447 } else if (reqptr->parameter ==
1448 static_cast<uint8_t>(BootOptionParameter::BOOT_INFO)) {
1449 // Handle parameter #4 and return command completed normally
1450 // (IPMI_CC_OK). There is no implementation in OpenBMC for this
1451 // parameter. This is added to support the ipmitool command `chassis
1452 // bootdev` which sends set on parameter #4, before setting the boot
1453 // flags.
1454 rc = IPMI_CC_OK;
1455 } else {
shgoupfd84fbbf2015-12-17 10:05:51 +08001456 fprintf(stderr, "Unsupported parameter 0x%x\n", reqptr->parameter);
1457 rc = IPMI_CC_PARM_NOT_SUPPORTED;
Adriana Kobylak40814c62015-10-27 15:58:44 -05001458 }
1459
1460 return rc;
1461}
1462
1463void register_netfn_chassis_functions()
1464{
Tom05732372016-09-06 17:21:23 +05301465 // <Wildcard Command>
Adriana Kobylak40814c62015-10-27 15:58:44 -05001466 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_CHASSIS, IPMI_CMD_WILDCARD);
Tom05732372016-09-06 17:21:23 +05301467 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_WILDCARD, NULL, ipmi_chassis_wildcard,
1468 PRIVILEGE_USER);
Adriana Kobylak40814c62015-10-27 15:58:44 -05001469
Tom05732372016-09-06 17:21:23 +05301470 // Get Chassis Capabilities
Nan Li8d15fb42016-08-16 22:29:40 +08001471 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_CHASSIS, IPMI_CMD_GET_CHASSIS_CAP);
Tom05732372016-09-06 17:21:23 +05301472 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_GET_CHASSIS_CAP, NULL, ipmi_get_chassis_cap,
1473 PRIVILEGE_USER);
Nan Li8d15fb42016-08-16 22:29:40 +08001474
Tom05732372016-09-06 17:21:23 +05301475 // <Get System Boot Options>
Adriana Kobylak40814c62015-10-27 15:58:44 -05001476 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_CHASSIS, IPMI_CMD_GET_SYS_BOOT_OPTIONS);
Tom05732372016-09-06 17:21:23 +05301477 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_GET_SYS_BOOT_OPTIONS, NULL,
1478 ipmi_chassis_get_sys_boot_options, PRIVILEGE_OPERATOR);
Adriana Kobylak40814c62015-10-27 15:58:44 -05001479
Tom05732372016-09-06 17:21:23 +05301480 // <Get Chassis Status>
Nan Lifdd8ec52016-08-28 03:57:40 +08001481 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_CHASSIS, IPMI_CMD_CHASSIS_STATUS);
Tom05732372016-09-06 17:21:23 +05301482 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_CHASSIS_STATUS, NULL, ipmi_get_chassis_status,
1483 PRIVILEGE_USER);
Nan Lifdd8ec52016-08-28 03:57:40 +08001484
Tom05732372016-09-06 17:21:23 +05301485 // <Chassis Control>
vishwa36993272015-11-20 12:43:49 -06001486 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_CHASSIS, IPMI_CMD_CHASSIS_CONTROL);
Tom05732372016-09-06 17:21:23 +05301487 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_CHASSIS_CONTROL, NULL, ipmi_chassis_control,
1488 PRIVILEGE_OPERATOR);
shgoupfd84fbbf2015-12-17 10:05:51 +08001489
James Feist5bfbde32017-11-22 13:40:53 -08001490 // <Chassis Identify>
1491 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_CHASSIS, IPMI_CMD_CHASSIS_IDENTIFY);
1492 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_CHASSIS_IDENTIFY, NULL,
1493 ipmi_chassis_identify, PRIVILEGE_OPERATOR);
1494
Tom05732372016-09-06 17:21:23 +05301495 // <Set System Boot Options>
shgoupfd84fbbf2015-12-17 10:05:51 +08001496 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n", NETFUN_CHASSIS, IPMI_CMD_SET_SYS_BOOT_OPTIONS);
Tom05732372016-09-06 17:21:23 +05301497 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_SET_SYS_BOOT_OPTIONS, NULL,
1498 ipmi_chassis_set_sys_boot_options, PRIVILEGE_OPERATOR);
vishwa36993272015-11-20 12:43:49 -06001499}