blob: b9d4290052650c0c1a317e2cf23adfc2fe37f072 [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>
20#include <experimental/filesystem>
Ratan Guptadcb10672017-07-10 10:33:50 +053021#include <string>
Deepak Kodihalli8cc19362017-07-21 11:18:38 -050022#include <map>
Ratan Guptadcb10672017-07-10 10:33:50 +053023
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +053024#include <phosphor-logging/log.hpp>
Ratan Guptadcb10672017-07-10 10:33:50 +053025#include <phosphor-logging/elog-errors.hpp>
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +053026#include <xyz/openbmc_project/State/Host/server.hpp>
Ratan Guptadcb10672017-07-10 10:33:50 +053027#include "xyz/openbmc_project/Common/error.hpp"
28
29#include <sdbusplus/bus.hpp>
30#include <sdbusplus/server/object.hpp>
Deepak Kodihalli8cc19362017-07-21 11:18:38 -050031#include <xyz/openbmc_project/Control/Boot/Source/server.hpp>
32#include <xyz/openbmc_project/Control/Boot/Mode/server.hpp>
Deepak Kodihalli18b70d12017-07-21 13:36:33 -050033#include <xyz/openbmc_project/Control/Power/RestorePolicy/server.hpp>
Ratan Guptadcb10672017-07-10 10:33:50 +053034
Vishwanatha Subbannab891a572017-03-31 11:34:48 +053035#include "config.h"
ratagupta6f6bff2016-04-04 06:20:11 -050036
37//Defines
Ratan Guptafd28dd72016-08-01 04:58:01 -050038#define SET_PARM_VERSION 0x01
39#define SET_PARM_BOOT_FLAGS_PERMANENT 0x40 //boot flags data1 7th bit on
ratagupta6f6bff2016-04-04 06:20:11 -050040#define SET_PARM_BOOT_FLAGS_VALID_ONE_TIME 0x80 //boot flags data1 8th bit on
Ratan Guptafd28dd72016-08-01 04:58:01 -050041#define SET_PARM_BOOT_FLAGS_VALID_PERMANENT 0xC0 //boot flags data1 7 & 8 bit on
ratagupta6f6bff2016-04-04 06:20:11 -050042
Ratan Guptafd28dd72016-08-01 04:58:01 -050043constexpr size_t SIZE_MAC = 18;
44constexpr size_t SIZE_BOOT_OPTION = (uint8_t)BootOptionResponseSize::
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -050045 OPAL_NETWORK_SETTINGS;//Maximum size of the boot option parametrs
Ratan Guptafd28dd72016-08-01 04:58:01 -050046constexpr size_t SIZE_PREFIX = 7;
47constexpr size_t MAX_PREFIX_VALUE = 32;
48constexpr size_t SIZE_COOKIE = 4;
49constexpr size_t SIZE_VERSION = 2;
Ratan Gupta6ec7daa2017-07-15 14:13:01 +053050
Ratan Guptafd28dd72016-08-01 04:58:01 -050051//PetiBoot-Specific
Ratan Gupta6ec7daa2017-07-15 14:13:01 +053052static constexpr uint8_t net_conf_initial_bytes[] = {0x80, 0x21, 0x70, 0x62,
53 0x21, 0x00, 0x01, 0x06};
Ratan Guptafd28dd72016-08-01 04:58:01 -050054
55static constexpr size_t COOKIE_OFFSET = 1;
56static constexpr size_t VERSION_OFFSET = 5;
Ratan Gupta6ec7daa2017-07-15 14:13:01 +053057static constexpr size_t ADDR_SIZE_OFFSET = 8;
Ratan Guptafd28dd72016-08-01 04:58:01 -050058static constexpr size_t MAC_OFFSET = 9;
59static constexpr size_t ADDRTYPE_OFFSET = 16;
60static constexpr size_t IPADDR_OFFSET = 17;
ratagupta6f6bff2016-04-04 06:20:11 -050061
shgoupfd84fbbf2015-12-17 10:05:51 +080062
Adriana Kobylak40814c62015-10-27 15:58:44 -050063void register_netfn_chassis_functions() __attribute__((constructor));
64
shgoupfd84fbbf2015-12-17 10:05:51 +080065// Host settings in dbus
66// Service name should be referenced by connection name got via object mapper
67const char *settings_object_name = "/org/openbmc/settings/host0";
68const char *settings_intf_name = "org.freedesktop.DBus.Properties";
69const char *host_intf_name = "org.openbmc.settings.Host";
70
Ratan Guptadcb10672017-07-10 10:33:50 +053071constexpr auto SETTINGS_ROOT = "/";
72constexpr auto SETTINGS_MATCH = "host0";
Ratan Guptadcb10672017-07-10 10:33:50 +053073
74constexpr auto IP_INTERFACE = "xyz.openbmc_project.Network.IP";
75constexpr auto MAC_INTERFACE = "xyz.openbmc_project.Network.MACAddress";
76
Ratan Guptadcb10672017-07-10 10:33:50 +053077
Nan Li8d15fb42016-08-16 22:29:40 +080078typedef struct
79{
80 uint8_t cap_flags;
81 uint8_t fru_info_dev_addr;
82 uint8_t sdr_dev_addr;
83 uint8_t sel_dev_addr;
84 uint8_t system_management_dev_addr;
85 uint8_t bridge_dev_addr;
86}__attribute__((packed)) ipmi_chassis_cap_t;
87
Nan Lifdd8ec52016-08-28 03:57:40 +080088typedef struct
89{
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -050090 uint8_t cur_power_state;
91 uint8_t last_power_event;
92 uint8_t misc_power_state;
93 uint8_t front_panel_button_cap_status;
Nan Lifdd8ec52016-08-28 03:57:40 +080094}__attribute__((packed)) ipmi_get_chassis_status_t;
95
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +053096// Phosphor Host State manager
97namespace State = sdbusplus::xyz::openbmc_project::State::server;
98
Andrew Geisslera6e3a302017-05-31 19:34:00 -050099namespace fs = std::experimental::filesystem;
100
Ratan Guptadcb10672017-07-10 10:33:50 +0530101using namespace phosphor::logging;
102using namespace sdbusplus::xyz::openbmc_project::Common::Error;
103
Deepak Kodihalli8cc19362017-07-21 11:18:38 -0500104namespace chassis
105{
106namespace internal
107{
108
109constexpr auto bootModeIntf = "xyz.openbmc_project.Control.Boot.Mode";
110constexpr auto bootSourceIntf = "xyz.openbmc_project.Control.Boot.Source";
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500111constexpr auto powerRestoreIntf =
112 "xyz.openbmc_project.Control.Power.RestorePolicy";
Deepak Kodihalli8cc19362017-07-21 11:18:38 -0500113sdbusplus::bus::bus dbus(ipmid_get_sd_bus_connection());
114
115namespace cache
116{
117
118settings::Objects objects(dbus,
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500119 {bootModeIntf, bootSourceIntf, powerRestoreIntf});
Deepak Kodihalli8cc19362017-07-21 11:18:38 -0500120
121} // namespace cache
122} // namespace internal
123} // namespace chassis
124
Ratan Guptadcb10672017-07-10 10:33:50 +0530125//TODO : Can remove the below function as we have
126// new functions which uses sdbusplus.
127//
128// openbmc/openbmc#1489
ratagupta6f6bff2016-04-04 06:20:11 -0500129int dbus_get_property(const char *name, char **buf)
shgoupfd84fbbf2015-12-17 10:05:51 +0800130{
131 sd_bus_error error = SD_BUS_ERROR_NULL;
132 sd_bus_message *m = NULL;
133 sd_bus *bus = NULL;
134 char *temp_buf = NULL;
135 char *connection = NULL;
136 int r;
137
Brad Bishop35518682016-07-22 08:35:41 -0400138 // Get the system bus where most system services are provided.
139 bus = ipmid_get_sd_bus_connection();
shgoupfd84fbbf2015-12-17 10:05:51 +0800140
Brad Bishop35518682016-07-22 08:35:41 -0400141 r = mapper_get_service(bus, settings_object_name, &connection);
shgoupfd84fbbf2015-12-17 10:05:51 +0800142 if (r < 0) {
Brad Bishop819ddd42016-10-05 21:19:19 -0400143 fprintf(stderr, "Failed to get %s connection: %s\n",
144 settings_object_name, strerror(-r));
shgoupfd84fbbf2015-12-17 10:05:51 +0800145 goto finish;
146 }
147
shgoupfd84fbbf2015-12-17 10:05:51 +0800148 /*
149 * Bus, service, object path, interface and method are provided to call
150 * the method.
151 * Signatures and input arguments are provided by the arguments at the
152 * end.
153 */
154 r = sd_bus_call_method(bus,
155 connection, /* service to contact */
156 settings_object_name, /* object path */
157 settings_intf_name, /* interface name */
158 "Get", /* method name */
159 &error, /* object to return error in */
160 &m, /* return message on success */
161 "ss", /* input signature */
162 host_intf_name, /* first argument */
ratagupta6f6bff2016-04-04 06:20:11 -0500163 name); /* second argument */
shgoupfd84fbbf2015-12-17 10:05:51 +0800164
165 if (r < 0) {
166 fprintf(stderr, "Failed to issue method call: %s\n", error.message);
167 goto finish;
168 }
169
170 /*
171 * The output should be parsed exactly the same as the output formatting
172 * specified.
173 */
174 r = sd_bus_message_read(m, "v", "s", &temp_buf);
175 if (r < 0) {
176 fprintf(stderr, "Failed to parse response message: %s\n", strerror(-r));
177 goto finish;
178 }
179
Matthew Barth56181052017-01-23 09:36:29 -0600180 *buf = strdup(temp_buf);
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500181 /* *buf = (char*) malloc(strlen(temp_buf));
shgoupfd84fbbf2015-12-17 10:05:51 +0800182 if (*buf) {
183 strcpy(*buf, temp_buf);
184 }
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500185 */
shgoupfd84fbbf2015-12-17 10:05:51 +0800186 printf("IPMID boot option property get: {%s}.\n", (char *) temp_buf);
187
188finish:
189 sd_bus_error_free(&error);
190 sd_bus_message_unref(m);
191 free(connection);
192
193 return r;
194}
195
Ratan Guptadcb10672017-07-10 10:33:50 +0530196//TODO : Can remove the below function as we have
197// new functions which uses sdbusplus.
198//
199// openbmc/openbmc#1489
200
ratagupta6f6bff2016-04-04 06:20:11 -0500201int dbus_set_property(const char * name, const char *value)
shgoupfd84fbbf2015-12-17 10:05:51 +0800202{
203 sd_bus_error error = SD_BUS_ERROR_NULL;
204 sd_bus_message *m = NULL;
205 sd_bus *bus = NULL;
206 char *connection = NULL;
207 int r;
208
Brad Bishop35518682016-07-22 08:35:41 -0400209 // Get the system bus where most system services are provided.
210 bus = ipmid_get_sd_bus_connection();
shgoupfd84fbbf2015-12-17 10:05:51 +0800211
Brad Bishop35518682016-07-22 08:35:41 -0400212 r = mapper_get_service(bus, settings_object_name, &connection);
shgoupfd84fbbf2015-12-17 10:05:51 +0800213 if (r < 0) {
Brad Bishop819ddd42016-10-05 21:19:19 -0400214 fprintf(stderr, "Failed to get %s connection: %s\n",
215 settings_object_name, strerror(-r));
shgoupfd84fbbf2015-12-17 10:05:51 +0800216 goto finish;
217 }
218
shgoupfd84fbbf2015-12-17 10:05:51 +0800219 /*
220 * Bus, service, object path, interface and method are provided to call
221 * the method.
222 * Signatures and input arguments are provided by the arguments at the
223 * end.
224 */
225 r = sd_bus_call_method(bus,
226 connection, /* service to contact */
227 settings_object_name, /* object path */
228 settings_intf_name, /* interface name */
229 "Set", /* method name */
230 &error, /* object to return error in */
231 &m, /* return message on success */
232 "ssv", /* input signature */
233 host_intf_name, /* first argument */
ratagupta6f6bff2016-04-04 06:20:11 -0500234 name, /* second argument */
shgoupfd84fbbf2015-12-17 10:05:51 +0800235 "s", /* third argument */
ratagupta6f6bff2016-04-04 06:20:11 -0500236 value); /* fourth argument */
shgoupfd84fbbf2015-12-17 10:05:51 +0800237
238 if (r < 0) {
239 fprintf(stderr, "Failed to issue method call: %s\n", error.message);
240 goto finish;
241 }
242
ratagupta6f6bff2016-04-04 06:20:11 -0500243 printf("IPMID boot option property set: {%s}.\n", value);
shgoupfd84fbbf2015-12-17 10:05:51 +0800244
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500245 finish:
shgoupfd84fbbf2015-12-17 10:05:51 +0800246 sd_bus_error_free(&error);
247 sd_bus_message_unref(m);
248 free(connection);
249
250 return r;
251}
252
Adriana Kobylak40814c62015-10-27 15:58:44 -0500253struct get_sys_boot_options_t {
254 uint8_t parameter;
255 uint8_t set;
256 uint8_t block;
257} __attribute__ ((packed));
258
shgoupfd84fbbf2015-12-17 10:05:51 +0800259struct get_sys_boot_options_response_t {
260 uint8_t version;
261 uint8_t parm;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500262 uint8_t data[SIZE_BOOT_OPTION];
shgoupfd84fbbf2015-12-17 10:05:51 +0800263} __attribute__ ((packed));
264
265struct set_sys_boot_options_t {
266 uint8_t parameter;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500267 uint8_t data[SIZE_BOOT_OPTION];
shgoupfd84fbbf2015-12-17 10:05:51 +0800268} __attribute__ ((packed));
269
Ratan Guptafd28dd72016-08-01 04:58:01 -0500270
Ratan Guptadcb10672017-07-10 10:33:50 +0530271int getHostNetworkData(get_sys_boot_options_response_t* respptr)
Ratan Guptafd28dd72016-08-01 04:58:01 -0500272{
Ratan Guptadcb10672017-07-10 10:33:50 +0530273 ipmi::PropertyMap properties;
274 int rc = 0;
Ratan Gupta8c31d232017-08-13 05:49:43 +0530275 uint8_t addrSize = ipmi::network::IPV4_ADDRESS_SIZE_BYTE;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500276
Ratan Guptadcb10672017-07-10 10:33:50 +0530277 try
278 {
279 //TODO There may be cases where an interface is implemented by multiple
280 // objects,to handle such cases we are interested on that object
281 // which are on interested busname.
282 // Currenlty mapper doesn't give the readable busname(gives busid)
283 // so we can't match with bus name so giving some object specific info
284 // as SETTINGS_MATCH.
285 // Later SETTINGS_MATCH will be replaced with busname.
Ratan Guptafd28dd72016-08-01 04:58:01 -0500286
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530287 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
Ratan Guptadcb10672017-07-10 10:33:50 +0530288
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530289 auto ipObjectInfo = ipmi::getDbusObject(bus, IP_INTERFACE,
290 SETTINGS_ROOT, SETTINGS_MATCH);
291
292 auto macObjectInfo = ipmi::getDbusObject(bus, MAC_INTERFACE,
293 SETTINGS_ROOT, SETTINGS_MATCH);
294
295 properties = ipmi::getAllDbusProperties(bus, ipObjectInfo.second,
296 ipObjectInfo.first, IP_INTERFACE);
Ratan Guptacc8feb42017-07-25 21:52:10 +0530297 auto variant =
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530298 ipmi::getDbusProperty(bus, macObjectInfo.second,
299 macObjectInfo.first,
Ratan Guptacc8feb42017-07-25 21:52:10 +0530300 MAC_INTERFACE, "MACAddress");
Ratan Guptadcb10672017-07-10 10:33:50 +0530301
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530302 auto ipAddress = properties["Address"].get<std::string>();
Ratan Guptad70f4532017-08-04 02:07:31 +0530303
304 auto gateway = properties["Gateway"].get<std::string>();
305
306 auto prefix = properties["PrefixLength"].get<uint8_t>();
307
308 uint8_t isStatic = (properties["Origin"].get<std::string>() ==
309 "xyz.openbmc_project.Network.IP.AddressOrigin.Static")
310 ? 1 : 0;
311
Ratan Guptacc8feb42017-07-25 21:52:10 +0530312 auto MACAddress = variant.get<std::string>();
313
Ratan Guptad70f4532017-08-04 02:07:31 +0530314 // it is expected here that we should get the valid data
315 // but we may also get the default values.
316 // Validation of the data is done by settings.
317 //
318 // if mac address is default mac address then
319 // don't send blank override.
Ratan Gupta8c31d232017-08-13 05:49:43 +0530320 if ((MACAddress == ipmi::network::DEFAULT_MAC_ADDRESS))
Ratan Guptad70f4532017-08-04 02:07:31 +0530321 {
322 memset(respptr->data, 0, SIZE_BOOT_OPTION);
323 rc = -1;
324 return rc;
325 }
326 // if addr is static then ipaddress,gateway,prefix
327 // should not be default one,don't send blank override.
328 if (isStatic)
329 {
Ratan Gupta8c31d232017-08-13 05:49:43 +0530330 if((ipAddress == ipmi::network::DEFAULT_ADDRESS) ||
331 (gateway == ipmi::network::DEFAULT_ADDRESS) ||
Ratan Guptad70f4532017-08-04 02:07:31 +0530332 (!prefix))
333 {
334 memset(respptr->data, 0, SIZE_BOOT_OPTION);
335 rc = -1;
336 return rc;
337 }
338 }
339
Ratan Gupta8c31d232017-08-13 05:49:43 +0530340 sscanf(MACAddress.c_str(), ipmi::network::MAC_ADDRESS_FORMAT,
Ratan Guptadcb10672017-07-10 10:33:50 +0530341 (respptr->data + MAC_OFFSET),
342 (respptr->data + MAC_OFFSET + 1),
343 (respptr->data + MAC_OFFSET + 2),
344 (respptr->data + MAC_OFFSET + 3),
345 (respptr->data + MAC_OFFSET + 4),
346 (respptr->data + MAC_OFFSET + 5));
347
Ratan Guptadcb10672017-07-10 10:33:50 +0530348 respptr->data[MAC_OFFSET + 6] = 0x00;
349
Ratan Guptad70f4532017-08-04 02:07:31 +0530350 memcpy(respptr->data + ADDRTYPE_OFFSET, &isStatic,
351 sizeof(isStatic));
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530352
353 uint8_t addressFamily = (properties["Type"].get<std::string>() ==
354 "xyz.openbmc_project.Network.IP.Protocol.IPv4") ?
355 AF_INET : AF_INET6;
356
Ratan Gupta8c31d232017-08-13 05:49:43 +0530357 addrSize = (addressFamily == AF_INET) ?
358 ipmi::network::IPV4_ADDRESS_SIZE_BYTE :
359 ipmi::network::IPV6_ADDRESS_SIZE_BYTE;
Ratan Guptadcb10672017-07-10 10:33:50 +0530360
361 // ipaddress and gateway would be in IPv4 format
Ratan Guptad70f4532017-08-04 02:07:31 +0530362 inet_pton(addressFamily, ipAddress.c_str(),
363 (respptr->data + IPADDR_OFFSET));
Ratan Guptadcb10672017-07-10 10:33:50 +0530364
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530365 uint8_t prefixOffset = IPADDR_OFFSET + addrSize;
366
367 memcpy(respptr->data + prefixOffset, &prefix, sizeof(prefix));
368
369 uint8_t gatewayOffset = prefixOffset + sizeof(decltype(prefix));
370
Ratan Guptad70f4532017-08-04 02:07:31 +0530371 inet_pton(addressFamily, gateway.c_str(),
372 (respptr->data + gatewayOffset));
Ratan Guptadcb10672017-07-10 10:33:50 +0530373
374 }
375 catch (InternalFailure& e)
376 {
377 commit<InternalFailure>();
378 memset(respptr->data, 0, SIZE_BOOT_OPTION);
379 rc = -1;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500380 return rc;
381 }
382
Ratan Guptadcb10672017-07-10 10:33:50 +0530383 //PetiBoot-Specific
384 //If sucess then copy the first 9 bytes to the data
Ratan Guptadcb10672017-07-10 10:33:50 +0530385 memcpy(respptr->data, net_conf_initial_bytes,
386 sizeof(net_conf_initial_bytes));
Ratan Guptafd28dd72016-08-01 04:58:01 -0500387
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530388 memcpy(respptr->data + ADDR_SIZE_OFFSET, &addrSize, sizeof(addrSize));
389
Ratan Guptafd28dd72016-08-01 04:58:01 -0500390#ifdef _IPMI_DEBUG_
Ratan Guptadcb10672017-07-10 10:33:50 +0530391 printf("\n===Printing the IPMI Formatted Data========\n");
Ratan Guptafd28dd72016-08-01 04:58:01 -0500392
Ratan Guptadcb10672017-07-10 10:33:50 +0530393 for (uint8_t pos = 0; pos < index; pos++)
394 {
395 printf("%02x ", respptr->data[pos]);
396 }
Ratan Guptafd28dd72016-08-01 04:58:01 -0500397#endif
398
Ratan Guptafd28dd72016-08-01 04:58:01 -0500399 return rc;
400}
401
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530402/** @brief convert IPv4 and IPv6 addresses from binary to text form.
403 * @param[in] family - IPv4/Ipv6
404 * @param[in] data - req data pointer.
405 * @param[in] offset - offset in the data.
406 * @param[in] addrSize - size of the data which needs to be read from offset.
407 * @returns address in text form.
408 */
409
410std::string getAddrStr(uint8_t family, uint8_t* data,
411 uint8_t offset, uint8_t addrSize)
412{
413 char ipAddr[INET6_ADDRSTRLEN] = {};
414
415 switch(family)
416 {
417 case AF_INET:
418 {
419 struct sockaddr_in addr4 {};
420 memcpy(&addr4.sin_addr.s_addr, &data[offset], addrSize);
421
422 inet_ntop(AF_INET, &addr4.sin_addr,
423 ipAddr, INET_ADDRSTRLEN);
424
425 break;
426 }
427 case AF_INET6:
428 {
429 struct sockaddr_in6 addr6 {};
430 memcpy(&addr6.sin6_addr.s6_addr, &data[offset], addrSize);
431
432 inet_ntop(AF_INET6, &addr6.sin6_addr,
433 ipAddr, INET6_ADDRSTRLEN);
434
435 break;
436 }
437 default:
438 {
439 return {};
440 }
441 }
442
443 return ipAddr;
444}
445
Ratan Guptadcb10672017-07-10 10:33:50 +0530446int setHostNetworkData(set_sys_boot_options_t* reqptr)
Ratan Guptafd28dd72016-08-01 04:58:01 -0500447{
Ratan Guptadcb10672017-07-10 10:33:50 +0530448 using namespace std::string_literals;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500449 std::string host_network_config;
Ratan Guptad70f4532017-08-04 02:07:31 +0530450 char mac[] {"00:00:00:00:00:00"};
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530451 std::string ipAddress, gateway;
452 char addrOrigin {0};
453 uint8_t addrSize {0};
Ratan Guptadcb10672017-07-10 10:33:50 +0530454 std::string addressOrigin =
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530455 "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP";
456 std::string addressType =
457 "xyz.openbmc_project.Network.IP.Protocol.IPv4";
Ratan Guptadcb10672017-07-10 10:33:50 +0530458 uint8_t prefix {0};
459 uint32_t zeroCookie = 0;
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530460 uint8_t family = AF_INET;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500461
462 //cookie starts from second byte
463 // version starts from sixth byte
464
Ratan Guptadcb10672017-07-10 10:33:50 +0530465 try
Ratan Guptafd28dd72016-08-01 04:58:01 -0500466 {
Ratan Guptadcb10672017-07-10 10:33:50 +0530467 do
468 {
469 // cookie == 0x21 0x70 0x62 0x21
470 if (memcmp(&(reqptr->data[COOKIE_OFFSET]),
471 (net_conf_initial_bytes + COOKIE_OFFSET),
472 SIZE_COOKIE) != 0)
473 {
474 //cookie == 0
475 if (memcmp(&(reqptr->data[COOKIE_OFFSET]),
476 &zeroCookie,
477 SIZE_COOKIE) == 0)
478 {
479 // need to zero out the network settings.
480 break;
481 }
482
483 log<level::ERR>("Invalid Cookie");
484 elog<InternalFailure>();
485 }
486
487 // vesion == 0x00 0x01
488 if (memcmp(&(reqptr->data[VERSION_OFFSET]),
489 (net_conf_initial_bytes + VERSION_OFFSET),
490 SIZE_VERSION) != 0)
491 {
492
493 log<level::ERR>("Invalid Version");
494 elog<InternalFailure>();
495 }
496
Ratan Gupta8c31d232017-08-13 05:49:43 +0530497 snprintf(mac, SIZE_MAC, ipmi::network::MAC_ADDRESS_FORMAT,
Ratan Guptadcb10672017-07-10 10:33:50 +0530498 reqptr->data[MAC_OFFSET],
499 reqptr->data[MAC_OFFSET + 1],
500 reqptr->data[MAC_OFFSET + 2],
501 reqptr->data[MAC_OFFSET + 3],
502 reqptr->data[MAC_OFFSET + 4],
503 reqptr->data[MAC_OFFSET + 5]);
504
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530505 memcpy(&addrOrigin, &(reqptr->data[ADDRTYPE_OFFSET]),
506 sizeof(decltype(addrOrigin)));
Ratan Guptadcb10672017-07-10 10:33:50 +0530507
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530508 if (addrOrigin)
Ratan Guptadcb10672017-07-10 10:33:50 +0530509 {
510 addressOrigin =
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530511 "xyz.openbmc_project.Network.IP.AddressOrigin.Static";
Ratan Guptadcb10672017-07-10 10:33:50 +0530512 }
513
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530514 // Get the address size
515 memcpy(&addrSize ,&reqptr->data[ADDR_SIZE_OFFSET], sizeof(addrSize));
Ratan Guptadcb10672017-07-10 10:33:50 +0530516
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530517 uint8_t prefixOffset = IPADDR_OFFSET + addrSize;
Ratan Guptadcb10672017-07-10 10:33:50 +0530518
Ratan Guptad70f4532017-08-04 02:07:31 +0530519 memcpy(&prefix, &(reqptr->data[prefixOffset]),
520 sizeof(decltype(prefix)));
Ratan Guptadcb10672017-07-10 10:33:50 +0530521
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530522 uint8_t gatewayOffset = prefixOffset + sizeof(decltype(prefix));
523
Ratan Gupta8c31d232017-08-13 05:49:43 +0530524 if (addrSize != ipmi::network::IPV4_ADDRESS_SIZE_BYTE)
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530525 {
526 addressType = "xyz.openbmc_project.Network.IP.Protocol.IPv6";
527 family = AF_INET6;
528 }
529
530 ipAddress = getAddrStr(family, reqptr->data, IPADDR_OFFSET, addrSize);
Ratan Guptad70f4532017-08-04 02:07:31 +0530531
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530532 gateway = getAddrStr(family, reqptr->data, gatewayOffset, addrSize);
533
Ratan Guptadcb10672017-07-10 10:33:50 +0530534 } while(0);
535
Ratan Guptafd28dd72016-08-01 04:58:01 -0500536 //Cookie == 0 or it is a valid cookie
Ratan Guptadcb10672017-07-10 10:33:50 +0530537 host_network_config += "ipaddress="s + ipAddress +
538 ",prefix="s + std::to_string(prefix) + ",gateway="s + gateway +
539 ",mac="s + mac + ",addressOrigin="s + addressOrigin;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500540
Ratan Guptafd28dd72016-08-01 04:58:01 -0500541
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530542 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
543
544 auto ipObjectInfo = ipmi::getDbusObject(bus, IP_INTERFACE,
545 SETTINGS_ROOT, SETTINGS_MATCH);
546 auto macObjectInfo = ipmi::getDbusObject(bus, MAC_INTERFACE,
547 SETTINGS_ROOT, SETTINGS_MATCH);
Ratan Guptadcb10672017-07-10 10:33:50 +0530548 // set the dbus property
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530549 ipmi::setDbusProperty(bus, ipObjectInfo.second, ipObjectInfo.first,
Ratan Guptadcb10672017-07-10 10:33:50 +0530550 IP_INTERFACE, "Address", std::string(ipAddress));
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530551 ipmi::setDbusProperty(bus, ipObjectInfo.second, ipObjectInfo.first,
Ratan Guptadcb10672017-07-10 10:33:50 +0530552 IP_INTERFACE, "PrefixLength", prefix);
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530553 ipmi::setDbusProperty(bus, ipObjectInfo.second, ipObjectInfo.first,
Ratan Guptadcb10672017-07-10 10:33:50 +0530554 IP_INTERFACE, "Origin", addressOrigin);
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530555 ipmi::setDbusProperty(bus, ipObjectInfo.second, ipObjectInfo.first,
Ratan Guptadcb10672017-07-10 10:33:50 +0530556 IP_INTERFACE, "Gateway", std::string(gateway));
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530557 ipmi::setDbusProperty(bus, ipObjectInfo.second, ipObjectInfo.first,
Ratan Guptadcb10672017-07-10 10:33:50 +0530558 IP_INTERFACE, "Type",
559 std::string("xyz.openbmc_project.Network.IP.Protocol.IPv4"));
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530560 ipmi::setDbusProperty(bus, macObjectInfo.second, macObjectInfo.first,
Ratan Guptadcb10672017-07-10 10:33:50 +0530561 MAC_INTERFACE,"MACAddress", std::string(mac));
Ratan Guptafd28dd72016-08-01 04:58:01 -0500562
Ratan Guptad70f4532017-08-04 02:07:31 +0530563 log<level::DEBUG>("Network configuration changed",
564 entry("NETWORKCONFIG=%s", host_network_config.c_str()));
565
Ratan Guptafd28dd72016-08-01 04:58:01 -0500566 }
Ratan Guptadcb10672017-07-10 10:33:50 +0530567 catch (InternalFailure& e)
568 {
569 commit<InternalFailure>();
570 return -1;
571 }
572
573 return 0;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500574}
575
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500576ipmi_ret_t ipmi_chassis_wildcard(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
577 ipmi_request_t request,
578 ipmi_response_t response,
579 ipmi_data_len_t data_len,
580 ipmi_context_t context)
Adriana Kobylak40814c62015-10-27 15:58:44 -0500581{
582 printf("Handling CHASSIS WILDCARD Netfn:[0x%X], Cmd:[0x%X]\n",netfn, cmd);
583 // Status code.
Nan Li70aa8d92016-08-29 00:11:10 +0800584 ipmi_ret_t rc = IPMI_CC_INVALID;
Adriana Kobylak40814c62015-10-27 15:58:44 -0500585 *data_len = 0;
586 return rc;
587}
588
Nan Li8d15fb42016-08-16 22:29:40 +0800589ipmi_ret_t ipmi_get_chassis_cap(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500590 ipmi_request_t request, ipmi_response_t response,
591 ipmi_data_len_t data_len, ipmi_context_t context)
Nan Li8d15fb42016-08-16 22:29:40 +0800592{
593 // sd_bus error
594 ipmi_ret_t rc = IPMI_CC_OK;
595
596 ipmi_chassis_cap_t chassis_cap{};
597
598 *data_len = sizeof(ipmi_chassis_cap_t);
599
600 // TODO: need future work. Get those flag from MRW.
601
602 // capabilities flags
603 // [7..4] - reserved
604 // [3] – 1b = provides power interlock (IPM 1.5)
605 // [2] – 1b = provides Diagnostic Interrupt (FP NMI)
606 // [1] – 1b = provides “Front Panel Lockout” (indicates that the chassis has capabilities
607 // to lock out external power control and reset button or front panel interfaces
608 // and/or detect tampering with those interfaces).
609 // [0] -1b = Chassis provides intrusion (physical security) sensor.
610 // set to default value 0x0.
611 chassis_cap.cap_flags = 0x0;
612
613 // Since we do not have a separate SDR Device/SEL Device/ FRU repository.
614 // The 20h was given as those 5 device addresses.
615 // Chassis FRU info Device Address
616 chassis_cap.fru_info_dev_addr = 0x20;
617
618 // Chassis SDR Device Address
619 chassis_cap.sdr_dev_addr = 0x20;
620
621 // Chassis SEL Device Address
622 chassis_cap.sel_dev_addr = 0x20;
623
624 // Chassis System Management Device Address
625 chassis_cap.system_management_dev_addr = 0x20;
626
627 // Chassis Bridge Device Address.
628 chassis_cap.bridge_dev_addr = 0x20;
629
630 memcpy(response, &chassis_cap, *data_len);
631
632 return rc;
633}
634
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530635//------------------------------------------
636// Calls into Host State Manager Dbus object
637//------------------------------------------
638int initiate_state_transition(State::Host::Transition transition)
vishwa36993272015-11-20 12:43:49 -0600639{
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500640 // OpenBMC Host State Manager dbus framework
641 constexpr auto HOST_STATE_MANAGER_ROOT = "/xyz/openbmc_project/state/host0";
642 constexpr auto HOST_STATE_MANAGER_IFACE = "xyz.openbmc_project.State.Host";
643 constexpr auto DBUS_PROPERTY_IFACE = "org.freedesktop.DBus.Properties";
644 constexpr auto PROPERTY = "RequestedHostTransition";
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530645
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500646 // sd_bus error
647 int rc = 0;
648 char *busname = NULL;
vishwa36993272015-11-20 12:43:49 -0600649
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500650 // SD Bus error report mechanism.
651 sd_bus_error bus_error = SD_BUS_ERROR_NULL;
vishwa36993272015-11-20 12:43:49 -0600652
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500653 // Gets a hook onto either a SYSTEM or SESSION bus
654 sd_bus *bus_type = ipmid_get_sd_bus_connection();
655 rc = mapper_get_service(bus_type, HOST_STATE_MANAGER_ROOT, &busname);
656 if (rc < 0)
657 {
658 log<level::ERR>("Failed to get bus name",
659 entry("ERROR=%s, OBJPATH=%s",
660 strerror(-rc), HOST_STATE_MANAGER_ROOT));
661 return rc;
662 }
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530663
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500664 // Convert to string equivalent of the passed in transition enum.
665 auto request = State::convertForMessage(transition);
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530666
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500667 rc = sd_bus_call_method(bus_type, // On the system bus
668 busname, // Service to contact
669 HOST_STATE_MANAGER_ROOT, // Object path
670 DBUS_PROPERTY_IFACE, // Interface name
671 "Set", // Method to be called
672 &bus_error, // object to return error
673 nullptr, // Response buffer if any
674 "ssv", // Takes 3 arguments
675 HOST_STATE_MANAGER_IFACE,
676 PROPERTY,
677 "s", request.c_str());
678 if(rc < 0)
679 {
680 log<level::ERR>("Failed to initiate transition",
681 entry("ERROR=%s, REQUEST=%s",
682 bus_error.message, request.c_str()));
683 }
684 else
685 {
686 log<level::INFO>("Transition request initiated successfully");
687 }
vishwa36993272015-11-20 12:43:49 -0600688
689 sd_bus_error_free(&bus_error);
Sergey Solomineb9b8142016-08-23 09:07:28 -0500690 free(busname);
vishwa36993272015-11-20 12:43:49 -0600691
Sergey Solomineb9b8142016-08-23 09:07:28 -0500692 return rc;
vishwa36993272015-11-20 12:43:49 -0600693}
694
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500695namespace power_policy
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500696{
Nan Lifdd8ec52016-08-28 03:57:40 +0800697
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500698using namespace sdbusplus::xyz::openbmc_project::Control::Power::server;
699using IpmiValue = uint8_t;
700using DbusValue = RestorePolicy::Policy;
Nan Lifdd8ec52016-08-28 03:57:40 +0800701
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500702std::map<DbusValue, IpmiValue> dbusToIpmi =
703{
704 {RestorePolicy::Policy::AlwaysOff, 0x00},
705 {RestorePolicy::Policy::Restore, 0x01},
706 {RestorePolicy::Policy::AlwaysOn, 0x02}
707};
Nan Lifdd8ec52016-08-28 03:57:40 +0800708
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500709} // namespace power_policy
Nan Lifdd8ec52016-08-28 03:57:40 +0800710
711//----------------------------------------------------------------------
712// Get Chassis Status commands
713//----------------------------------------------------------------------
714ipmi_ret_t ipmi_get_chassis_status(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500715 ipmi_request_t request,
716 ipmi_response_t response,
717 ipmi_data_len_t data_len,
718 ipmi_context_t context)
Nan Lifdd8ec52016-08-28 03:57:40 +0800719{
720 const char *objname = "/org/openbmc/control/power0";
721 const char *intf = "org.openbmc.control.Power";
722
723 sd_bus *bus = NULL;
724 sd_bus_message *reply = NULL;
725 int r = 0;
726 int pgood = 0;
727 char *busname = NULL;
728 ipmi_ret_t rc = IPMI_CC_OK;
729 ipmi_get_chassis_status_t chassis_status{};
730
Nan Lifdd8ec52016-08-28 03:57:40 +0800731 uint8_t s = 0;
732
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500733 using namespace chassis::internal;
734 using namespace chassis::internal::cache;
735 using namespace power_policy;
736
Deepak Kodihallie6027092017-08-27 08:13:37 -0500737 const auto& powerRestoreSetting = objects.map.at(powerRestoreIntf).front();
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500738 auto method =
739 dbus.new_method_call(
740 objects.service(powerRestoreSetting, powerRestoreIntf).c_str(),
741 powerRestoreSetting.c_str(),
Ratan Guptacc8feb42017-07-25 21:52:10 +0530742 ipmi::PROP_INTF,
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500743 "Get");
744 method.append(powerRestoreIntf, "PowerRestorePolicy");
745 auto resp = dbus.call(method);
746 if (resp.is_method_error())
747 {
748 log<level::ERR>("Error in PowerRestorePolicy Get");
749 report<InternalFailure>();
750 *data_len = 0;
751 return IPMI_CC_UNSPECIFIED_ERROR;
752 }
753 sdbusplus::message::variant<std::string> result;
754 resp.read(result);
755 auto powerRestore =
756 RestorePolicy::convertPolicyFromString(result.get<std::string>());
Nan Lifdd8ec52016-08-28 03:57:40 +0800757
758 *data_len = 4;
759
Tom Joseph63a00512017-08-09 23:39:59 +0530760 bus = ipmid_get_sd_bus_connection();
761
Nan Lifdd8ec52016-08-28 03:57:40 +0800762 r = mapper_get_service(bus, objname, &busname);
763 if (r < 0) {
764 fprintf(stderr, "Failed to get bus name, return value: %s.\n", strerror(-r));
765 rc = IPMI_CC_UNSPECIFIED_ERROR;
766 goto finish;
767 }
768
769 r = sd_bus_get_property(bus, busname, objname, intf, "pgood", NULL, &reply, "i");
770 if (r < 0) {
771 fprintf(stderr, "Failed to call sd_bus_get_property:%d, %s\n", r, strerror(-r));
772 fprintf(stderr, "Bus: %s, Path: %s, Interface: %s\n",
773 busname, objname, intf);
774 rc = IPMI_CC_UNSPECIFIED_ERROR;
775 goto finish;
776 }
777
778 r = sd_bus_message_read(reply, "i", &pgood);
779 if (r < 0) {
780 fprintf(stderr, "Failed to read sensor: %s\n", strerror(-r));
781 rc = IPMI_CC_UNSPECIFIED_ERROR;
782 goto finish;
783 }
784
785 printf("pgood is 0x%02x\n", pgood);
786
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500787 s = dbusToIpmi.at(powerRestore);
Nan Lifdd8ec52016-08-28 03:57:40 +0800788
789 // Current Power State
790 // [7] reserved
791 // [6..5] power restore policy
792 // 00b = chassis stays powered off after AC/mains returns
793 // 01b = after AC returns, power is restored to the state that was
794 // in effect when AC/mains was lost.
795 // 10b = chassis always powers up after AC/mains returns
796 // 11b = unknow
797 // Set to 00b, by observing the hardware behavior.
798 // Do we need to define a dbus property to identify the restore policy?
799
800 // [4] power control fault
801 // 1b = controller attempted to turn system power on or off, but
802 // system did not enter desired state.
803 // Set to 0b, since We don't support it..
804
805 // [3] power fault
806 // 1b = fault detected in main power subsystem.
807 // set to 0b. for we don't support it.
808
809 // [2] 1b = interlock (chassis is presently shut down because a chassis
810 // panel interlock switch is active). (IPMI 1.5)
811 // set to 0b, for we don't support it.
812
813 // [1] power overload
814 // 1b = system shutdown because of power overload condition.
815 // set to 0b, for we don't support it.
816
817 // [0] power is on
818 // 1b = system power is on
819 // 0b = system power is off(soft-off S4/S5, or mechanical off)
820
821 chassis_status.cur_power_state = ((s & 0x3)<<5) | (pgood & 0x1);
822
823 // Last Power Event
824 // [7..5] – reserved
825 // [4] – 1b = last ‘Power is on’ state was entered via IPMI command
826 // [3] – 1b = last power down caused by power fault
827 // [2] – 1b = last power down caused by a power interlock being activated
828 // [1] – 1b = last power down caused by a Power overload
829 // [0] – 1b = AC failed
830 // set to 0x0, for we don't support these fields.
831
832 chassis_status.last_power_event = 0;
833
834 // Misc. Chassis State
835 // [7] – reserved
836 // [6] – 1b = Chassis Identify command and state info supported (Optional)
837 // 0b = Chassis Identify command support unspecified via this command.
838 // (The Get Command Support command , if implemented, would still
839 // indicate support for the Chassis Identify command)
840 // [5..4] – Chassis Identify State. Mandatory when bit[6] =1b, reserved (return
841 // as 00b) otherwise. Returns the present chassis identify state.
842 // Refer to the Chassis Identify command for more info.
843 // 00b = chassis identify state = Off
844 // 01b = chassis identify state = Temporary(timed) On
845 // 10b = chassis identify state = Indefinite On
846 // 11b = reserved
847 // [3] – 1b = Cooling/fan fault detected
848 // [2] – 1b = Drive Fault
849 // [1] – 1b = Front Panel Lockout active (power off and reset via chassis
850 // push-buttons disabled.)
851 // [0] – 1b = Chassis Intrusion active
852 // set to 0, for we don't support them.
853 chassis_status.misc_power_state = 0;
854
855 // Front Panel Button Capabilities and disable/enable status(Optional)
856 // set to 0, for we don't support them.
857 chassis_status.front_panel_button_cap_status = 0;
858
859 // Pack the actual response
860 memcpy(response, &chassis_status, *data_len);
861
862finish:
863 free(busname);
864 reply = sd_bus_message_unref(reply);
865
866 return rc;
867}
Chris Austen7888c4d2015-12-03 15:26:20 -0600868
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +0530869//-------------------------------------------------------------
870// Send a command to SoftPowerOff application to stop any timer
871//-------------------------------------------------------------
872int stop_soft_off_timer()
873{
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +0530874 constexpr auto iface = "org.freedesktop.DBus.Properties";
875 constexpr auto soft_off_iface = "xyz.openbmc_project.Ipmi.Internal."
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500876 "SoftPowerOff";
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +0530877
878 constexpr auto property = "ResponseReceived";
879 constexpr auto value = "xyz.openbmc_project.Ipmi.Internal."
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500880 "SoftPowerOff.HostResponse.HostShutdown";
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +0530881
882 // Get the system bus where most system services are provided.
883 auto bus = ipmid_get_sd_bus_connection();
884
885 // Get the service name
Andrew Geissler2b4e4592017-06-08 11:18:35 -0500886 // TODO openbmc/openbmc#1661 - Mapper refactor
887 //
888 // See openbmc/openbmc#1743 for some details but high level summary is that
889 // for now the code will directly call the soft off interface due to a
890 // race condition with mapper usage
891 //
892 //char *busname = nullptr;
893 //auto r = mapper_get_service(bus, SOFTOFF_OBJPATH, &busname);
894 //if (r < 0)
895 //{
896 // fprintf(stderr, "Failed to get %s bus name: %s\n",
897 // SOFTOFF_OBJPATH, strerror(-r));
898 // return r;
899 //}
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +0530900
901 // No error object or reply expected.
Andrew Geissler2b4e4592017-06-08 11:18:35 -0500902 int rc = sd_bus_call_method(bus, SOFTOFF_BUSNAME, SOFTOFF_OBJPATH, iface,
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500903 "Set", nullptr, nullptr, "ssv",
904 soft_off_iface, property, "s", value);
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +0530905 if (rc < 0)
906 {
907 fprintf(stderr, "Failed to set property in SoftPowerOff object: %s\n",
908 strerror(-rc));
909 }
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500910
Andrew Geissler2b4e4592017-06-08 11:18:35 -0500911 //TODO openbmc/openbmc#1661 - Mapper refactor
912 //free(busname);
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +0530913 return rc;
914}
915
vishwa36993272015-11-20 12:43:49 -0600916//----------------------------------------------------------------------
Andrew Geisslera6e3a302017-05-31 19:34:00 -0500917// Create file to indicate there is no need for softoff notification to host
918//----------------------------------------------------------------------
919void indicate_no_softoff_needed()
920{
921 fs::path path{HOST_INBAND_REQUEST_DIR};
922 if (!fs::is_directory(path))
923 {
924 fs::create_directory(path);
925 }
926
927 // Add the host instance (default 0 for now) to the file name
928 std::string file{HOST_INBAND_REQUEST_FILE};
929 auto size = std::snprintf(nullptr,0,file.c_str(),0);
930 size++; // null
931 std::unique_ptr<char[]> buf(new char[size]);
932 std::snprintf(buf.get(),size,file.c_str(),0);
933
934 // Append file name to directory and create it
935 path /= buf.get();
936 std::ofstream(path.c_str());
937}
938
939//----------------------------------------------------------------------
vishwa36993272015-11-20 12:43:49 -0600940// Chassis Control commands
941//----------------------------------------------------------------------
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500942ipmi_ret_t ipmi_chassis_control(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
943 ipmi_request_t request,
944 ipmi_response_t response,
945 ipmi_data_len_t data_len,
946 ipmi_context_t context)
vishwa36993272015-11-20 12:43:49 -0600947{
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500948 // Error from power off.
949 int rc = 0;
vishwa36993272015-11-20 12:43:49 -0600950
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500951 // No response for this command.
vishwa36993272015-11-20 12:43:49 -0600952 *data_len = 0;
953
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500954 // Catch the actual operaton by peeking into request buffer
955 uint8_t chassis_ctrl_cmd = *(uint8_t *)request;
956 printf("Chassis Control Command: Operation:[0x%X]\n",chassis_ctrl_cmd);
vishwa36993272015-11-20 12:43:49 -0600957
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500958 switch(chassis_ctrl_cmd)
959 {
960 case CMD_POWER_ON:
961 rc = initiate_state_transition(State::Host::Transition::On);
962 break;
963 case CMD_POWER_OFF:
Vishwanatha Subbanna8b26d352017-08-04 18:35:18 +0530964 // This path would be hit in 2 conditions.
965 // 1: When user asks for power off using ipmi chassis command 0x04
966 // 2: Host asking for power off post shutting down.
967
968 // If it's a host requested power off, then need to nudge Softoff
969 // application that it needs to stop the watchdog timer if running.
970 // If it is a user requested power off, then this is not really
971 // needed. But then we need to differentiate between user and host
972 // calling this same command
973
974 // For now, we are going ahead with trying to nudge the soft off and
975 // interpret the failure to do so as a non softoff case
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500976 rc = stop_soft_off_timer();
Vishwanatha Subbanna8b26d352017-08-04 18:35:18 +0530977
Andrew Geisslera6e3a302017-05-31 19:34:00 -0500978 // Only request the Off transition if the soft power off
979 // application is not running
980 if (rc < 0)
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500981 {
Andrew Geisslera6e3a302017-05-31 19:34:00 -0500982 // First create a file to indicate to the soft off application
Vishwanatha Subbanna8b26d352017-08-04 18:35:18 +0530983 // that it should not run. Not doing this will result in State
984 // manager doing a default soft power off when asked for power
985 // off.
Andrew Geisslera6e3a302017-05-31 19:34:00 -0500986 indicate_no_softoff_needed();
987
988 // Now request the shutdown
989 rc = initiate_state_transition(State::Host::Transition::Off);
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500990 }
Andrew Geisslera6e3a302017-05-31 19:34:00 -0500991 else
992 {
Vishwanatha Subbanna8b26d352017-08-04 18:35:18 +0530993 log<level::INFO>("Soft off is running, so let shutdown target "
994 "stop the host");
Andrew Geisslera6e3a302017-05-31 19:34:00 -0500995 }
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500996 break;
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +0530997
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500998 case CMD_HARD_RESET:
999 case CMD_POWER_CYCLE:
1000 // SPEC has a section that says certain implementations can trigger
1001 // PowerOn if power is Off when a command to power cycle is
1002 // requested
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001003
1004 // First create a file to indicate to the soft off application
1005 // that it should not run since this is a direct user initiated
1006 // power reboot request (i.e. a reboot request that is not
1007 // originating via a soft power off SMS request)
1008 indicate_no_softoff_needed();
1009
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001010 rc = initiate_state_transition(State::Host::Transition::Reboot);
1011 break;
Vishwanatha Subbanna8b26d352017-08-04 18:35:18 +05301012
1013 case CMD_SOFT_OFF_VIA_OVER_TEMP:
1014 // Request Host State Manager to do a soft power off
1015 rc = initiate_state_transition(State::Host::Transition::Off);
1016 break;
1017
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001018 default:
1019 {
1020 fprintf(stderr, "Invalid Chassis Control command:[0x%X] received\n",chassis_ctrl_cmd);
1021 rc = -1;
1022 }
1023 }
vishwa36993272015-11-20 12:43:49 -06001024
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001025 return ( (rc < 0) ? IPMI_CC_INVALID : IPMI_CC_OK);
vishwa36993272015-11-20 12:43:49 -06001026}
1027
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001028namespace boot_options
1029{
1030
1031using namespace sdbusplus::xyz::openbmc_project::Control::Boot::server;
1032using IpmiValue = uint8_t;
1033constexpr auto ipmiDefault = 0;
1034
1035std::map<IpmiValue, Source::Sources> sourceIpmiToDbus =
1036{
1037 {0x01, Source::Sources::Network},
1038 {0x02, Source::Sources::Disk},
1039 {0x05, Source::Sources::ExternalMedia},
1040 {ipmiDefault, Source::Sources::Default}
shgoupfd84fbbf2015-12-17 10:05:51 +08001041};
1042
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001043std::map<IpmiValue, Mode::Modes> modeIpmiToDbus =
1044{
1045 {0x03, Mode::Modes::Safe},
1046 {0x06, Mode::Modes::Setup},
1047 {ipmiDefault, Mode::Modes::Regular}
shgoupfd84fbbf2015-12-17 10:05:51 +08001048};
1049
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001050std::map<Source::Sources, IpmiValue> sourceDbusToIpmi =
1051{
1052 {Source::Sources::Network, 0x01},
1053 {Source::Sources::Disk, 0x02},
1054 {Source::Sources::ExternalMedia, 0x05},
1055 {Source::Sources::Default, ipmiDefault}
1056};
shgoupfd84fbbf2015-12-17 10:05:51 +08001057
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001058std::map<Mode::Modes, IpmiValue> modeDbusToIpmi =
1059{
1060 {Mode::Modes::Safe, 0x03},
1061 {Mode::Modes::Setup, 0x06},
1062 {Mode::Modes::Regular, ipmiDefault}
1063};
shgoupfd84fbbf2015-12-17 10:05:51 +08001064
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001065} // namespace boot_options
shgoupfd84fbbf2015-12-17 10:05:51 +08001066
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001067ipmi_ret_t ipmi_chassis_get_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1068 ipmi_request_t request,
1069 ipmi_response_t response,
1070 ipmi_data_len_t data_len,
1071 ipmi_context_t context)
Adriana Kobylak40814c62015-10-27 15:58:44 -05001072{
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001073 using namespace boot_options;
shgoupfd84fbbf2015-12-17 10:05:51 +08001074 ipmi_ret_t rc = IPMI_CC_PARM_NOT_SUPPORTED;
1075 char *p = NULL;
1076 get_sys_boot_options_response_t *resp = (get_sys_boot_options_response_t *) response;
1077 get_sys_boot_options_t *reqptr = (get_sys_boot_options_t*) request;
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001078 IpmiValue bootOption = ipmiDefault;
Adriana Kobylak40814c62015-10-27 15:58:44 -05001079
1080 printf("IPMI GET_SYS_BOOT_OPTIONS\n");
1081
shgoupfd84fbbf2015-12-17 10:05:51 +08001082 memset(resp,0,sizeof(*resp));
1083 resp->version = SET_PARM_VERSION;
1084 resp->parm = 5;
ratagupta6f6bff2016-04-04 06:20:11 -05001085 resp->data[0] = SET_PARM_BOOT_FLAGS_VALID_ONE_TIME;
Adriana Kobylak40814c62015-10-27 15:58:44 -05001086
Adriana Kobylak40814c62015-10-27 15:58:44 -05001087
shgoupfd84fbbf2015-12-17 10:05:51 +08001088 /*
1089 * Parameter #5 means boot flags. Please refer to 28.13 of ipmi doc.
1090 * This is the only parameter used by petitboot.
1091 */
Ratan Guptafd28dd72016-08-01 04:58:01 -05001092 if ( reqptr->parameter == static_cast<uint8_t>
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001093 ( BootOptionParameter::BOOT_FLAGS )) {
shgoupfd84fbbf2015-12-17 10:05:51 +08001094
Ratan Guptafd28dd72016-08-01 04:58:01 -05001095 *data_len = static_cast<uint8_t>(BootOptionResponseSize::BOOT_FLAGS);
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001096 using namespace chassis::internal;
1097 using namespace chassis::internal::cache;
shgoupfd84fbbf2015-12-17 10:05:51 +08001098
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001099 try
ratagupta6f6bff2016-04-04 06:20:11 -05001100 {
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001101 auto bootSetting = settings::boot::setting(objects, bootSourceIntf);
1102 const auto& bootSourceSetting =
1103 std::get<settings::Path>(bootSetting);
1104 auto oneTimeEnabled =
1105 std::get<settings::boot::OneTimeEnabled>(bootSetting);
1106 auto method =
1107 dbus.new_method_call(
1108 objects.service(bootSourceSetting, bootSourceIntf).c_str(),
1109 bootSourceSetting.c_str(),
1110 ipmi::PROP_INTF,
1111 "Get");
1112 method.append(bootSourceIntf, "BootSource");
1113 auto reply = dbus.call(method);
1114 if (reply.is_method_error())
1115 {
1116 log<level::ERR>("Error in BootSource Get");
1117 report<InternalFailure>();
1118 *data_len = 0;
1119 return IPMI_CC_UNSPECIFIED_ERROR;
1120 }
1121 sdbusplus::message::variant<std::string> result;
1122 reply.read(result);
1123 auto bootSource =
1124 Source::convertSourcesFromString(result.get<std::string>());
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001125
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001126 bootSetting = settings::boot::setting(objects, bootModeIntf);
1127 const auto& bootModeSetting = std::get<settings::Path>(bootSetting);
1128 method = dbus.new_method_call(
1129 objects.service(bootModeSetting, bootModeIntf).
1130 c_str(),
1131 bootModeSetting.c_str(),
1132 ipmi::PROP_INTF,
1133 "Get");
1134 method.append(bootModeIntf, "BootMode");
1135 reply = dbus.call(method);
1136 if (reply.is_method_error())
1137 {
1138 log<level::ERR>("Error in BootMode Get");
1139 report<InternalFailure>();
1140 *data_len = 0;
1141 return IPMI_CC_UNSPECIFIED_ERROR;
1142 }
1143 reply.read(result);
1144 auto bootMode =
1145 Mode::convertModesFromString(result.get<std::string>());
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001146
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001147 bootOption = sourceDbusToIpmi.at(bootSource);
1148 if ((Mode::Modes::Regular == bootMode) &&
1149 (Source::Sources::Default == bootSource))
1150 {
1151 bootOption = ipmiDefault;
1152 }
1153 else if (Source::Sources::Default == bootSource)
1154 {
1155 bootOption = modeDbusToIpmi.at(bootMode);
1156 }
1157 resp->data[1] = (bootOption << 2);
ratagupta6f6bff2016-04-04 06:20:11 -05001158
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001159 resp->data[0] = oneTimeEnabled ?
1160 SET_PARM_BOOT_FLAGS_VALID_ONE_TIME:
1161 SET_PARM_BOOT_FLAGS_VALID_PERMANENT;
ratagupta6f6bff2016-04-04 06:20:11 -05001162
ratagupta6f6bff2016-04-04 06:20:11 -05001163 rc = IPMI_CC_OK;
ratagupta6f6bff2016-04-04 06:20:11 -05001164 }
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001165 catch (InternalFailure& e)
1166 {
1167 report<InternalFailure>();
1168 *data_len = 0;
1169 return IPMI_CC_UNSPECIFIED_ERROR;
1170 }
Ratan Guptafd28dd72016-08-01 04:58:01 -05001171 } else if ( reqptr->parameter == static_cast<uint8_t>
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001172 ( BootOptionParameter::OPAL_NETWORK_SETTINGS )) {
Ratan Guptafd28dd72016-08-01 04:58:01 -05001173
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001174 *data_len = static_cast<uint8_t>(BootOptionResponseSize::OPAL_NETWORK_SETTINGS);
Ratan Guptafd28dd72016-08-01 04:58:01 -05001175
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001176 resp->parm = static_cast<uint8_t>(BootOptionParameter::OPAL_NETWORK_SETTINGS);
Ratan Guptafd28dd72016-08-01 04:58:01 -05001177
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001178 int ret = getHostNetworkData(resp);
Ratan Guptafd28dd72016-08-01 04:58:01 -05001179
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001180 if (ret < 0) {
Ratan Guptafd28dd72016-08-01 04:58:01 -05001181
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001182 fprintf(stderr, "getHostNetworkData failed for get_sys_boot_options.\n");
1183 rc = IPMI_CC_UNSPECIFIED_ERROR;
Ratan Guptafd28dd72016-08-01 04:58:01 -05001184
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001185 }else
1186 rc = IPMI_CC_OK;
Ratan Guptafd28dd72016-08-01 04:58:01 -05001187 }
1188
1189 else {
Adriana Kobylak40814c62015-10-27 15:58:44 -05001190 fprintf(stderr, "Unsupported parameter 0x%x\n", reqptr->parameter);
shgoupfd84fbbf2015-12-17 10:05:51 +08001191 }
1192
1193 if (p)
1194 free(p);
1195
Ratan Guptafd28dd72016-08-01 04:58:01 -05001196 if (rc == IPMI_CC_OK)
1197 {
1198 *data_len += 2;
1199 }
1200
shgoupfd84fbbf2015-12-17 10:05:51 +08001201 return rc;
1202}
1203
1204
1205
1206ipmi_ret_t ipmi_chassis_set_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001207 ipmi_request_t request,
1208 ipmi_response_t response,
1209 ipmi_data_len_t data_len,
1210 ipmi_context_t context)
shgoupfd84fbbf2015-12-17 10:05:51 +08001211{
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001212 using namespace boot_options;
shgoupfd84fbbf2015-12-17 10:05:51 +08001213 ipmi_ret_t rc = IPMI_CC_OK;
shgoupfd84fbbf2015-12-17 10:05:51 +08001214 set_sys_boot_options_t *reqptr = (set_sys_boot_options_t *) request;
1215
Ratan Guptafd28dd72016-08-01 04:58:01 -05001216 printf("IPMI SET_SYS_BOOT_OPTIONS reqptr->parameter =[%d]\n",reqptr->parameter);
1217
shgoupfd84fbbf2015-12-17 10:05:51 +08001218 // This IPMI command does not have any resposne data
1219 *data_len = 0;
1220
1221 /* 000101
1222 * Parameter #5 means boot flags. Please refer to 28.13 of ipmi doc.
1223 * This is the only parameter used by petitboot.
1224 */
Ratan Guptafd28dd72016-08-01 04:58:01 -05001225
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001226 if (reqptr->parameter == (uint8_t)BootOptionParameter::BOOT_FLAGS)
1227 {
1228 IpmiValue bootOption = ((reqptr->data[1] & 0x3C) >> 2);
1229 using namespace chassis::internal;
1230 using namespace chassis::internal::cache;
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001231 auto oneTimeEnabled = false;
1232 constexpr auto enabledIntf = "xyz.openbmc_project.Object.Enable";
Tom Joseph57e8eb72017-09-25 18:05:02 +05301233 constexpr auto oneTimePath =
1234 "/xyz/openbmc_project/control/host0/boot/one_time";
shgoupfd84fbbf2015-12-17 10:05:51 +08001235
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001236 try
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001237 {
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001238 bool permanent =
1239 (reqptr->data[0] & SET_PARM_BOOT_FLAGS_PERMANENT) ==
1240 SET_PARM_BOOT_FLAGS_PERMANENT;
1241
Tom Joseph57e8eb72017-09-25 18:05:02 +05301242 auto bootSetting =
1243 settings::boot::setting(objects, bootSourceIntf);
1244
1245 oneTimeEnabled =
1246 std::get<settings::boot::OneTimeEnabled>(bootSetting);
1247
1248 /*
1249 * Check if the current boot setting is onetime or permanent, if the
1250 * request in the command is otherwise, then set the "Enabled"
1251 * property in one_time object path to 'True' to indicate onetime
1252 * and 'False' to indicate permanent.
1253 *
1254 * Once the onetime/permanent setting is applied, then the bootMode
1255 * and bootSource is updated for the corresponding object.
1256 */
1257 if ((permanent && oneTimeEnabled) ||
1258 (!permanent && !oneTimeEnabled))
1259 {
1260 auto service = ipmi::getService(dbus, enabledIntf, oneTimePath);
1261
1262 ipmi::setDbusProperty(dbus,
1263 service,
1264 oneTimePath,
1265 enabledIntf,
1266 "Enabled",
1267 !permanent);
1268 }
1269
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001270 auto modeItr = modeIpmiToDbus.find(bootOption);
1271 auto sourceItr = sourceIpmiToDbus.find(bootOption);
1272 if (sourceIpmiToDbus.end() != sourceItr)
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001273 {
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001274 sdbusplus::message::variant<std::string> property =
1275 convertForMessage(sourceItr->second);
Tom Joseph57e8eb72017-09-25 18:05:02 +05301276 auto bootSetting = settings::boot::setting(objects,
1277 bootSourceIntf);
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001278 const auto& bootSourceSetting =
1279 std::get<settings::Path>(bootSetting);
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001280 auto method =
1281 dbus.new_method_call(
1282 objects.service(bootSourceSetting, bootSourceIntf).
1283 c_str(),
1284 bootSourceSetting.c_str(),
1285 ipmi::PROP_INTF,
1286 "Set");
1287 method.append(bootSourceIntf, "BootSource", property);
1288 auto reply = dbus.call(method);
1289 if (reply.is_method_error())
1290 {
1291 log<level::ERR>("Error in BootSource Set");
1292 report<InternalFailure>();
1293 *data_len = 0;
1294 return IPMI_CC_UNSPECIFIED_ERROR;
1295 }
1296
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001297 }
1298 if (modeIpmiToDbus.end() != modeItr)
1299 {
1300 sdbusplus::message::variant<std::string> property =
1301 convertForMessage(modeItr->second);
Tom Joseph57e8eb72017-09-25 18:05:02 +05301302 auto bootSetting = settings::boot::setting(objects,
1303 bootModeIntf);
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001304 const auto& bootModeSetting =
1305 std::get<settings::Path>(bootSetting);
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001306 auto method =
1307 dbus.new_method_call(
1308 objects.service(bootModeSetting, bootModeIntf).c_str(),
1309 bootModeSetting.c_str(),
1310 ipmi::PROP_INTF,
1311 "Set");
1312 method.append(bootModeIntf, "BootMode", property);
1313 auto reply = dbus.call(method);
1314 if (reply.is_method_error())
1315 {
1316 log<level::ERR>("Error in BootMode Set");
1317 report<InternalFailure>();
1318 *data_len = 0;
1319 return IPMI_CC_UNSPECIFIED_ERROR;
1320 }
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001321 }
1322 }
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001323 catch (InternalFailure& e)
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001324 {
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001325 report<InternalFailure>();
1326 *data_len = 0;
1327 return IPMI_CC_UNSPECIFIED_ERROR;
shgoupfd84fbbf2015-12-17 10:05:51 +08001328 }
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001329 } else if (reqptr->parameter ==
1330 (uint8_t)BootOptionParameter::OPAL_NETWORK_SETTINGS) {
Ratan Guptafd28dd72016-08-01 04:58:01 -05001331
1332 int ret = setHostNetworkData(reqptr);
1333 if (ret < 0) {
1334 fprintf(stderr, "setHostNetworkData failed for set_sys_boot_options.\n");
1335 rc = IPMI_CC_UNSPECIFIED_ERROR;
1336 }
Tom Josephf536c902017-09-25 18:08:15 +05301337 } else if (reqptr->parameter ==
1338 static_cast<uint8_t>(BootOptionParameter::BOOT_INFO)) {
1339 // Handle parameter #4 and return command completed normally
1340 // (IPMI_CC_OK). There is no implementation in OpenBMC for this
1341 // parameter. This is added to support the ipmitool command `chassis
1342 // bootdev` which sends set on parameter #4, before setting the boot
1343 // flags.
1344 rc = IPMI_CC_OK;
1345 } else {
shgoupfd84fbbf2015-12-17 10:05:51 +08001346 fprintf(stderr, "Unsupported parameter 0x%x\n", reqptr->parameter);
1347 rc = IPMI_CC_PARM_NOT_SUPPORTED;
Adriana Kobylak40814c62015-10-27 15:58:44 -05001348 }
1349
1350 return rc;
1351}
1352
1353void register_netfn_chassis_functions()
1354{
Tom05732372016-09-06 17:21:23 +05301355 // <Wildcard Command>
Adriana Kobylak40814c62015-10-27 15:58:44 -05001356 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_CHASSIS, IPMI_CMD_WILDCARD);
Tom05732372016-09-06 17:21:23 +05301357 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_WILDCARD, NULL, ipmi_chassis_wildcard,
1358 PRIVILEGE_USER);
Adriana Kobylak40814c62015-10-27 15:58:44 -05001359
Tom05732372016-09-06 17:21:23 +05301360 // Get Chassis Capabilities
Nan Li8d15fb42016-08-16 22:29:40 +08001361 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_CHASSIS, IPMI_CMD_GET_CHASSIS_CAP);
Tom05732372016-09-06 17:21:23 +05301362 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_GET_CHASSIS_CAP, NULL, ipmi_get_chassis_cap,
1363 PRIVILEGE_USER);
Nan Li8d15fb42016-08-16 22:29:40 +08001364
Tom05732372016-09-06 17:21:23 +05301365 // <Get System Boot Options>
Adriana Kobylak40814c62015-10-27 15:58:44 -05001366 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_CHASSIS, IPMI_CMD_GET_SYS_BOOT_OPTIONS);
Tom05732372016-09-06 17:21:23 +05301367 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_GET_SYS_BOOT_OPTIONS, NULL,
1368 ipmi_chassis_get_sys_boot_options, PRIVILEGE_OPERATOR);
Adriana Kobylak40814c62015-10-27 15:58:44 -05001369
Tom05732372016-09-06 17:21:23 +05301370 // <Get Chassis Status>
Nan Lifdd8ec52016-08-28 03:57:40 +08001371 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_CHASSIS, IPMI_CMD_CHASSIS_STATUS);
Tom05732372016-09-06 17:21:23 +05301372 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_CHASSIS_STATUS, NULL, ipmi_get_chassis_status,
1373 PRIVILEGE_USER);
Nan Lifdd8ec52016-08-28 03:57:40 +08001374
Tom05732372016-09-06 17:21:23 +05301375 // <Chassis Control>
vishwa36993272015-11-20 12:43:49 -06001376 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_CHASSIS, IPMI_CMD_CHASSIS_CONTROL);
Tom05732372016-09-06 17:21:23 +05301377 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_CHASSIS_CONTROL, NULL, ipmi_chassis_control,
1378 PRIVILEGE_OPERATOR);
shgoupfd84fbbf2015-12-17 10:05:51 +08001379
Tom05732372016-09-06 17:21:23 +05301380 // <Set System Boot Options>
shgoupfd84fbbf2015-12-17 10:05:51 +08001381 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n", NETFUN_CHASSIS, IPMI_CMD_SET_SYS_BOOT_OPTIONS);
Tom05732372016-09-06 17:21:23 +05301382 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_SET_SYS_BOOT_OPTIONS, NULL,
1383 ipmi_chassis_set_sys_boot_options, PRIVILEGE_OPERATOR);
vishwa36993272015-11-20 12:43:49 -06001384}