blob: d392d55bb59a898bd19e1ebc43a43c6fc62a185f [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>
Tom Joseph5110c122018-03-23 17:55:40 +053020#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;
Tom Joseph5110c122018-03-23 17:55:40 +053052constexpr 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";
Tom Joseph5110c122018-03-23 17:55:40 +053073const 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) {
Aditya Saripalli5fb14602017-11-09 14:46:27 +0530148 log<level::ERR>("Failed to get connection",
149 entry("OBJ_NAME=%s", settings_object_name),
150 entry("ERRNO=0x%X", -r));
shgoupfd84fbbf2015-12-17 10:05:51 +0800151 goto finish;
152 }
153
shgoupfd84fbbf2015-12-17 10:05:51 +0800154 /*
155 * Bus, service, object path, interface and method are provided to call
156 * the method.
157 * Signatures and input arguments are provided by the arguments at the
158 * end.
159 */
160 r = sd_bus_call_method(bus,
161 connection, /* service to contact */
162 settings_object_name, /* object path */
163 settings_intf_name, /* interface name */
164 "Get", /* method name */
165 &error, /* object to return error in */
166 &m, /* return message on success */
167 "ss", /* input signature */
168 host_intf_name, /* first argument */
ratagupta6f6bff2016-04-04 06:20:11 -0500169 name); /* second argument */
shgoupfd84fbbf2015-12-17 10:05:51 +0800170
171 if (r < 0) {
Aditya Saripalli5fb14602017-11-09 14:46:27 +0530172 log<level::ERR>("Failed to issue Get method call",
173 entry("ERRNO=0x%X", r));
shgoupfd84fbbf2015-12-17 10:05:51 +0800174 goto finish;
175 }
176
177 /*
178 * The output should be parsed exactly the same as the output formatting
179 * specified.
180 */
181 r = sd_bus_message_read(m, "v", "s", &temp_buf);
182 if (r < 0) {
Aditya Saripalli5fb14602017-11-09 14:46:27 +0530183 log<level::ERR>("Failed to parse response message",
184 entry("ERRNO=0x%X", -r));
shgoupfd84fbbf2015-12-17 10:05:51 +0800185 goto finish;
186 }
187
Matthew Barth56181052017-01-23 09:36:29 -0600188 *buf = strdup(temp_buf);
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500189 /* *buf = (char*) malloc(strlen(temp_buf));
shgoupfd84fbbf2015-12-17 10:05:51 +0800190 if (*buf) {
191 strcpy(*buf, temp_buf);
192 }
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500193 */
Aditya Saripalli5fb14602017-11-09 14:46:27 +0530194
shgoupfd84fbbf2015-12-17 10:05:51 +0800195
196finish:
197 sd_bus_error_free(&error);
198 sd_bus_message_unref(m);
199 free(connection);
200
201 return r;
202}
203
Ratan Guptadcb10672017-07-10 10:33:50 +0530204//TODO : Can remove the below function as we have
205// new functions which uses sdbusplus.
206//
207// openbmc/openbmc#1489
208
ratagupta6f6bff2016-04-04 06:20:11 -0500209int dbus_set_property(const char * name, const char *value)
shgoupfd84fbbf2015-12-17 10:05:51 +0800210{
211 sd_bus_error error = SD_BUS_ERROR_NULL;
212 sd_bus_message *m = NULL;
213 sd_bus *bus = NULL;
214 char *connection = NULL;
215 int r;
216
Brad Bishop35518682016-07-22 08:35:41 -0400217 // Get the system bus where most system services are provided.
218 bus = ipmid_get_sd_bus_connection();
shgoupfd84fbbf2015-12-17 10:05:51 +0800219
Brad Bishop35518682016-07-22 08:35:41 -0400220 r = mapper_get_service(bus, settings_object_name, &connection);
shgoupfd84fbbf2015-12-17 10:05:51 +0800221 if (r < 0) {
Aditya Saripalli5fb14602017-11-09 14:46:27 +0530222 log<level::ERR>("Failed to get connection",
223 entry("OBJ_NAME=%s", settings_object_name),
224 entry("ERRNO=0x%X", -r));
shgoupfd84fbbf2015-12-17 10:05:51 +0800225 goto finish;
226 }
227
shgoupfd84fbbf2015-12-17 10:05:51 +0800228 /*
229 * Bus, service, object path, interface and method are provided to call
230 * the method.
231 * Signatures and input arguments are provided by the arguments at the
232 * end.
233 */
234 r = sd_bus_call_method(bus,
235 connection, /* service to contact */
236 settings_object_name, /* object path */
237 settings_intf_name, /* interface name */
238 "Set", /* method name */
239 &error, /* object to return error in */
240 &m, /* return message on success */
241 "ssv", /* input signature */
242 host_intf_name, /* first argument */
ratagupta6f6bff2016-04-04 06:20:11 -0500243 name, /* second argument */
shgoupfd84fbbf2015-12-17 10:05:51 +0800244 "s", /* third argument */
ratagupta6f6bff2016-04-04 06:20:11 -0500245 value); /* fourth argument */
shgoupfd84fbbf2015-12-17 10:05:51 +0800246
247 if (r < 0) {
Aditya Saripalli5fb14602017-11-09 14:46:27 +0530248 log<level::ERR>("Failed to issue Set method call",
249 entry("ERRNO=0x%X", r));
shgoupfd84fbbf2015-12-17 10:05:51 +0800250 goto finish;
251 }
252
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500253 finish:
shgoupfd84fbbf2015-12-17 10:05:51 +0800254 sd_bus_error_free(&error);
255 sd_bus_message_unref(m);
256 free(connection);
257
258 return r;
259}
260
Adriana Kobylak40814c62015-10-27 15:58:44 -0500261struct get_sys_boot_options_t {
262 uint8_t parameter;
263 uint8_t set;
264 uint8_t block;
265} __attribute__ ((packed));
266
shgoupfd84fbbf2015-12-17 10:05:51 +0800267struct get_sys_boot_options_response_t {
268 uint8_t version;
269 uint8_t parm;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500270 uint8_t data[SIZE_BOOT_OPTION];
shgoupfd84fbbf2015-12-17 10:05:51 +0800271} __attribute__ ((packed));
272
273struct set_sys_boot_options_t {
274 uint8_t parameter;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500275 uint8_t data[SIZE_BOOT_OPTION];
shgoupfd84fbbf2015-12-17 10:05:51 +0800276} __attribute__ ((packed));
277
Ratan Guptafd28dd72016-08-01 04:58:01 -0500278
Ratan Guptadcb10672017-07-10 10:33:50 +0530279int getHostNetworkData(get_sys_boot_options_response_t* respptr)
Ratan Guptafd28dd72016-08-01 04:58:01 -0500280{
Ratan Guptadcb10672017-07-10 10:33:50 +0530281 ipmi::PropertyMap properties;
282 int rc = 0;
Ratan Gupta8c31d232017-08-13 05:49:43 +0530283 uint8_t addrSize = ipmi::network::IPV4_ADDRESS_SIZE_BYTE;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500284
Ratan Guptadcb10672017-07-10 10:33:50 +0530285 try
286 {
287 //TODO There may be cases where an interface is implemented by multiple
288 // objects,to handle such cases we are interested on that object
289 // which are on interested busname.
290 // Currenlty mapper doesn't give the readable busname(gives busid)
291 // so we can't match with bus name so giving some object specific info
292 // as SETTINGS_MATCH.
293 // Later SETTINGS_MATCH will be replaced with busname.
Ratan Guptafd28dd72016-08-01 04:58:01 -0500294
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530295 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
Ratan Guptadcb10672017-07-10 10:33:50 +0530296
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530297 auto ipObjectInfo = ipmi::getDbusObject(bus, IP_INTERFACE,
298 SETTINGS_ROOT, SETTINGS_MATCH);
299
300 auto macObjectInfo = ipmi::getDbusObject(bus, MAC_INTERFACE,
301 SETTINGS_ROOT, SETTINGS_MATCH);
302
303 properties = ipmi::getAllDbusProperties(bus, ipObjectInfo.second,
304 ipObjectInfo.first, IP_INTERFACE);
Ratan Guptacc8feb42017-07-25 21:52:10 +0530305 auto variant =
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530306 ipmi::getDbusProperty(bus, macObjectInfo.second,
307 macObjectInfo.first,
Ratan Guptacc8feb42017-07-25 21:52:10 +0530308 MAC_INTERFACE, "MACAddress");
Ratan Guptadcb10672017-07-10 10:33:50 +0530309
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530310 auto ipAddress = properties["Address"].get<std::string>();
Ratan Guptad70f4532017-08-04 02:07:31 +0530311
312 auto gateway = properties["Gateway"].get<std::string>();
313
314 auto prefix = properties["PrefixLength"].get<uint8_t>();
315
316 uint8_t isStatic = (properties["Origin"].get<std::string>() ==
317 "xyz.openbmc_project.Network.IP.AddressOrigin.Static")
318 ? 1 : 0;
319
Ratan Guptacc8feb42017-07-25 21:52:10 +0530320 auto MACAddress = variant.get<std::string>();
321
Ratan Guptad70f4532017-08-04 02:07:31 +0530322 // it is expected here that we should get the valid data
323 // but we may also get the default values.
324 // Validation of the data is done by settings.
325 //
326 // if mac address is default mac address then
327 // don't send blank override.
Ratan Gupta8c31d232017-08-13 05:49:43 +0530328 if ((MACAddress == ipmi::network::DEFAULT_MAC_ADDRESS))
Ratan Guptad70f4532017-08-04 02:07:31 +0530329 {
330 memset(respptr->data, 0, SIZE_BOOT_OPTION);
331 rc = -1;
332 return rc;
333 }
334 // if addr is static then ipaddress,gateway,prefix
335 // should not be default one,don't send blank override.
336 if (isStatic)
337 {
Ratan Gupta8c31d232017-08-13 05:49:43 +0530338 if((ipAddress == ipmi::network::DEFAULT_ADDRESS) ||
339 (gateway == ipmi::network::DEFAULT_ADDRESS) ||
Ratan Guptad70f4532017-08-04 02:07:31 +0530340 (!prefix))
341 {
342 memset(respptr->data, 0, SIZE_BOOT_OPTION);
343 rc = -1;
344 return rc;
345 }
346 }
347
Ratan Gupta8c31d232017-08-13 05:49:43 +0530348 sscanf(MACAddress.c_str(), ipmi::network::MAC_ADDRESS_FORMAT,
Ratan Guptadcb10672017-07-10 10:33:50 +0530349 (respptr->data + MAC_OFFSET),
350 (respptr->data + MAC_OFFSET + 1),
351 (respptr->data + MAC_OFFSET + 2),
352 (respptr->data + MAC_OFFSET + 3),
353 (respptr->data + MAC_OFFSET + 4),
354 (respptr->data + MAC_OFFSET + 5));
355
Ratan Guptadcb10672017-07-10 10:33:50 +0530356 respptr->data[MAC_OFFSET + 6] = 0x00;
357
Ratan Guptad70f4532017-08-04 02:07:31 +0530358 memcpy(respptr->data + ADDRTYPE_OFFSET, &isStatic,
359 sizeof(isStatic));
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530360
361 uint8_t addressFamily = (properties["Type"].get<std::string>() ==
362 "xyz.openbmc_project.Network.IP.Protocol.IPv4") ?
363 AF_INET : AF_INET6;
364
Ratan Gupta8c31d232017-08-13 05:49:43 +0530365 addrSize = (addressFamily == AF_INET) ?
366 ipmi::network::IPV4_ADDRESS_SIZE_BYTE :
367 ipmi::network::IPV6_ADDRESS_SIZE_BYTE;
Ratan Guptadcb10672017-07-10 10:33:50 +0530368
369 // ipaddress and gateway would be in IPv4 format
Ratan Guptad70f4532017-08-04 02:07:31 +0530370 inet_pton(addressFamily, ipAddress.c_str(),
371 (respptr->data + IPADDR_OFFSET));
Ratan Guptadcb10672017-07-10 10:33:50 +0530372
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530373 uint8_t prefixOffset = IPADDR_OFFSET + addrSize;
374
375 memcpy(respptr->data + prefixOffset, &prefix, sizeof(prefix));
376
377 uint8_t gatewayOffset = prefixOffset + sizeof(decltype(prefix));
378
Ratan Guptad70f4532017-08-04 02:07:31 +0530379 inet_pton(addressFamily, gateway.c_str(),
380 (respptr->data + gatewayOffset));
Ratan Guptadcb10672017-07-10 10:33:50 +0530381
382 }
383 catch (InternalFailure& e)
384 {
385 commit<InternalFailure>();
386 memset(respptr->data, 0, SIZE_BOOT_OPTION);
387 rc = -1;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500388 return rc;
389 }
390
Ratan Guptadcb10672017-07-10 10:33:50 +0530391 //PetiBoot-Specific
Gunnar Mills8991dd62017-10-25 17:11:29 -0500392 //If success then copy the first 9 bytes to the data
Ratan Guptadcb10672017-07-10 10:33:50 +0530393 memcpy(respptr->data, net_conf_initial_bytes,
394 sizeof(net_conf_initial_bytes));
Ratan Guptafd28dd72016-08-01 04:58:01 -0500395
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530396 memcpy(respptr->data + ADDR_SIZE_OFFSET, &addrSize, sizeof(addrSize));
397
Ratan Guptafd28dd72016-08-01 04:58:01 -0500398#ifdef _IPMI_DEBUG_
Ratan Guptadcb10672017-07-10 10:33:50 +0530399 printf("\n===Printing the IPMI Formatted Data========\n");
Ratan Guptafd28dd72016-08-01 04:58:01 -0500400
Ratan Guptadcb10672017-07-10 10:33:50 +0530401 for (uint8_t pos = 0; pos < index; pos++)
402 {
403 printf("%02x ", respptr->data[pos]);
404 }
Ratan Guptafd28dd72016-08-01 04:58:01 -0500405#endif
406
Ratan Guptafd28dd72016-08-01 04:58:01 -0500407 return rc;
408}
409
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530410/** @brief convert IPv4 and IPv6 addresses from binary to text form.
411 * @param[in] family - IPv4/Ipv6
412 * @param[in] data - req data pointer.
413 * @param[in] offset - offset in the data.
414 * @param[in] addrSize - size of the data which needs to be read from offset.
415 * @returns address in text form.
416 */
417
418std::string getAddrStr(uint8_t family, uint8_t* data,
419 uint8_t offset, uint8_t addrSize)
420{
421 char ipAddr[INET6_ADDRSTRLEN] = {};
422
423 switch(family)
424 {
425 case AF_INET:
426 {
427 struct sockaddr_in addr4 {};
428 memcpy(&addr4.sin_addr.s_addr, &data[offset], addrSize);
429
430 inet_ntop(AF_INET, &addr4.sin_addr,
431 ipAddr, INET_ADDRSTRLEN);
432
433 break;
434 }
435 case AF_INET6:
436 {
437 struct sockaddr_in6 addr6 {};
438 memcpy(&addr6.sin6_addr.s6_addr, &data[offset], addrSize);
439
440 inet_ntop(AF_INET6, &addr6.sin6_addr,
441 ipAddr, INET6_ADDRSTRLEN);
442
443 break;
444 }
445 default:
446 {
447 return {};
448 }
449 }
450
451 return ipAddr;
452}
453
Ratan Guptadcb10672017-07-10 10:33:50 +0530454int setHostNetworkData(set_sys_boot_options_t* reqptr)
Ratan Guptafd28dd72016-08-01 04:58:01 -0500455{
Ratan Guptadcb10672017-07-10 10:33:50 +0530456 using namespace std::string_literals;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500457 std::string host_network_config;
Ratan Guptad70f4532017-08-04 02:07:31 +0530458 char mac[] {"00:00:00:00:00:00"};
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530459 std::string ipAddress, gateway;
460 char addrOrigin {0};
461 uint8_t addrSize {0};
Ratan Guptadcb10672017-07-10 10:33:50 +0530462 std::string addressOrigin =
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530463 "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP";
464 std::string addressType =
465 "xyz.openbmc_project.Network.IP.Protocol.IPv4";
Ratan Guptadcb10672017-07-10 10:33:50 +0530466 uint8_t prefix {0};
467 uint32_t zeroCookie = 0;
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530468 uint8_t family = AF_INET;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500469
470 //cookie starts from second byte
471 // version starts from sixth byte
472
Ratan Guptadcb10672017-07-10 10:33:50 +0530473 try
Ratan Guptafd28dd72016-08-01 04:58:01 -0500474 {
Ratan Guptadcb10672017-07-10 10:33:50 +0530475 do
476 {
477 // cookie == 0x21 0x70 0x62 0x21
478 if (memcmp(&(reqptr->data[COOKIE_OFFSET]),
479 (net_conf_initial_bytes + COOKIE_OFFSET),
480 SIZE_COOKIE) != 0)
481 {
482 //cookie == 0
483 if (memcmp(&(reqptr->data[COOKIE_OFFSET]),
484 &zeroCookie,
485 SIZE_COOKIE) == 0)
486 {
487 // need to zero out the network settings.
488 break;
489 }
490
491 log<level::ERR>("Invalid Cookie");
492 elog<InternalFailure>();
493 }
494
495 // vesion == 0x00 0x01
496 if (memcmp(&(reqptr->data[VERSION_OFFSET]),
497 (net_conf_initial_bytes + VERSION_OFFSET),
498 SIZE_VERSION) != 0)
499 {
500
501 log<level::ERR>("Invalid Version");
502 elog<InternalFailure>();
503 }
504
Ratan Gupta8c31d232017-08-13 05:49:43 +0530505 snprintf(mac, SIZE_MAC, ipmi::network::MAC_ADDRESS_FORMAT,
Ratan Guptadcb10672017-07-10 10:33:50 +0530506 reqptr->data[MAC_OFFSET],
507 reqptr->data[MAC_OFFSET + 1],
508 reqptr->data[MAC_OFFSET + 2],
509 reqptr->data[MAC_OFFSET + 3],
510 reqptr->data[MAC_OFFSET + 4],
511 reqptr->data[MAC_OFFSET + 5]);
512
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530513 memcpy(&addrOrigin, &(reqptr->data[ADDRTYPE_OFFSET]),
514 sizeof(decltype(addrOrigin)));
Ratan Guptadcb10672017-07-10 10:33:50 +0530515
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530516 if (addrOrigin)
Ratan Guptadcb10672017-07-10 10:33:50 +0530517 {
518 addressOrigin =
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530519 "xyz.openbmc_project.Network.IP.AddressOrigin.Static";
Ratan Guptadcb10672017-07-10 10:33:50 +0530520 }
521
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530522 // Get the address size
523 memcpy(&addrSize ,&reqptr->data[ADDR_SIZE_OFFSET], sizeof(addrSize));
Ratan Guptadcb10672017-07-10 10:33:50 +0530524
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530525 uint8_t prefixOffset = IPADDR_OFFSET + addrSize;
Ratan Guptadcb10672017-07-10 10:33:50 +0530526
Ratan Guptad70f4532017-08-04 02:07:31 +0530527 memcpy(&prefix, &(reqptr->data[prefixOffset]),
528 sizeof(decltype(prefix)));
Ratan Guptadcb10672017-07-10 10:33:50 +0530529
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530530 uint8_t gatewayOffset = prefixOffset + sizeof(decltype(prefix));
531
Ratan Gupta8c31d232017-08-13 05:49:43 +0530532 if (addrSize != ipmi::network::IPV4_ADDRESS_SIZE_BYTE)
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530533 {
534 addressType = "xyz.openbmc_project.Network.IP.Protocol.IPv6";
535 family = AF_INET6;
536 }
537
538 ipAddress = getAddrStr(family, reqptr->data, IPADDR_OFFSET, addrSize);
Ratan Guptad70f4532017-08-04 02:07:31 +0530539
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530540 gateway = getAddrStr(family, reqptr->data, gatewayOffset, addrSize);
541
Ratan Guptadcb10672017-07-10 10:33:50 +0530542 } while(0);
543
Ratan Guptafd28dd72016-08-01 04:58:01 -0500544 //Cookie == 0 or it is a valid cookie
Ratan Guptadcb10672017-07-10 10:33:50 +0530545 host_network_config += "ipaddress="s + ipAddress +
546 ",prefix="s + std::to_string(prefix) + ",gateway="s + gateway +
547 ",mac="s + mac + ",addressOrigin="s + addressOrigin;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500548
Ratan Guptafd28dd72016-08-01 04:58:01 -0500549
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530550 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
551
552 auto ipObjectInfo = ipmi::getDbusObject(bus, IP_INTERFACE,
553 SETTINGS_ROOT, SETTINGS_MATCH);
554 auto macObjectInfo = ipmi::getDbusObject(bus, MAC_INTERFACE,
555 SETTINGS_ROOT, SETTINGS_MATCH);
Ratan Guptadcb10672017-07-10 10:33:50 +0530556 // set the dbus property
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, "Address", std::string(ipAddress));
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530559 ipmi::setDbusProperty(bus, ipObjectInfo.second, ipObjectInfo.first,
Ratan Guptadcb10672017-07-10 10:33:50 +0530560 IP_INTERFACE, "PrefixLength", prefix);
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530561 ipmi::setDbusProperty(bus, ipObjectInfo.second, ipObjectInfo.first,
Ratan Guptadcb10672017-07-10 10:33:50 +0530562 IP_INTERFACE, "Origin", addressOrigin);
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530563 ipmi::setDbusProperty(bus, ipObjectInfo.second, ipObjectInfo.first,
Ratan Guptadcb10672017-07-10 10:33:50 +0530564 IP_INTERFACE, "Gateway", std::string(gateway));
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530565 ipmi::setDbusProperty(bus, ipObjectInfo.second, ipObjectInfo.first,
Ratan Guptadcb10672017-07-10 10:33:50 +0530566 IP_INTERFACE, "Type",
567 std::string("xyz.openbmc_project.Network.IP.Protocol.IPv4"));
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530568 ipmi::setDbusProperty(bus, macObjectInfo.second, macObjectInfo.first,
Ratan Guptadcb10672017-07-10 10:33:50 +0530569 MAC_INTERFACE,"MACAddress", std::string(mac));
Ratan Guptafd28dd72016-08-01 04:58:01 -0500570
Ratan Guptad70f4532017-08-04 02:07:31 +0530571 log<level::DEBUG>("Network configuration changed",
572 entry("NETWORKCONFIG=%s", host_network_config.c_str()));
573
Ratan Guptafd28dd72016-08-01 04:58:01 -0500574 }
Ratan Guptadcb10672017-07-10 10:33:50 +0530575 catch (InternalFailure& e)
576 {
577 commit<InternalFailure>();
578 return -1;
579 }
580
581 return 0;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500582}
583
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500584ipmi_ret_t ipmi_chassis_wildcard(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
585 ipmi_request_t request,
586 ipmi_response_t response,
587 ipmi_data_len_t data_len,
588 ipmi_context_t context)
Adriana Kobylak40814c62015-10-27 15:58:44 -0500589{
Adriana Kobylak40814c62015-10-27 15:58:44 -0500590 // Status code.
Nan Li70aa8d92016-08-29 00:11:10 +0800591 ipmi_ret_t rc = IPMI_CC_INVALID;
Adriana Kobylak40814c62015-10-27 15:58:44 -0500592 *data_len = 0;
593 return rc;
594}
595
Nan Li8d15fb42016-08-16 22:29:40 +0800596ipmi_ret_t ipmi_get_chassis_cap(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500597 ipmi_request_t request, ipmi_response_t response,
598 ipmi_data_len_t data_len, ipmi_context_t context)
Nan Li8d15fb42016-08-16 22:29:40 +0800599{
600 // sd_bus error
601 ipmi_ret_t rc = IPMI_CC_OK;
602
603 ipmi_chassis_cap_t chassis_cap{};
604
605 *data_len = sizeof(ipmi_chassis_cap_t);
606
607 // TODO: need future work. Get those flag from MRW.
608
609 // capabilities flags
610 // [7..4] - reserved
611 // [3] – 1b = provides power interlock (IPM 1.5)
612 // [2] – 1b = provides Diagnostic Interrupt (FP NMI)
613 // [1] – 1b = provides “Front Panel Lockout” (indicates that the chassis has capabilities
614 // to lock out external power control and reset button or front panel interfaces
615 // and/or detect tampering with those interfaces).
616 // [0] -1b = Chassis provides intrusion (physical security) sensor.
617 // set to default value 0x0.
618 chassis_cap.cap_flags = 0x0;
619
620 // Since we do not have a separate SDR Device/SEL Device/ FRU repository.
621 // The 20h was given as those 5 device addresses.
622 // Chassis FRU info Device Address
623 chassis_cap.fru_info_dev_addr = 0x20;
624
625 // Chassis SDR Device Address
626 chassis_cap.sdr_dev_addr = 0x20;
627
628 // Chassis SEL Device Address
629 chassis_cap.sel_dev_addr = 0x20;
630
631 // Chassis System Management Device Address
632 chassis_cap.system_management_dev_addr = 0x20;
633
634 // Chassis Bridge Device Address.
635 chassis_cap.bridge_dev_addr = 0x20;
636
637 memcpy(response, &chassis_cap, *data_len);
638
639 return rc;
640}
641
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530642//------------------------------------------
643// Calls into Host State Manager Dbus object
644//------------------------------------------
645int initiate_state_transition(State::Host::Transition transition)
vishwa36993272015-11-20 12:43:49 -0600646{
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500647 // OpenBMC Host State Manager dbus framework
648 constexpr auto HOST_STATE_MANAGER_ROOT = "/xyz/openbmc_project/state/host0";
649 constexpr auto HOST_STATE_MANAGER_IFACE = "xyz.openbmc_project.State.Host";
650 constexpr auto DBUS_PROPERTY_IFACE = "org.freedesktop.DBus.Properties";
651 constexpr auto PROPERTY = "RequestedHostTransition";
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530652
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500653 // sd_bus error
654 int rc = 0;
655 char *busname = NULL;
vishwa36993272015-11-20 12:43:49 -0600656
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500657 // SD Bus error report mechanism.
658 sd_bus_error bus_error = SD_BUS_ERROR_NULL;
vishwa36993272015-11-20 12:43:49 -0600659
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500660 // Gets a hook onto either a SYSTEM or SESSION bus
661 sd_bus *bus_type = ipmid_get_sd_bus_connection();
662 rc = mapper_get_service(bus_type, HOST_STATE_MANAGER_ROOT, &busname);
663 if (rc < 0)
664 {
665 log<level::ERR>("Failed to get bus name",
Aditya Saripalli5fb14602017-11-09 14:46:27 +0530666 entry("ERRNO=0x%X, OBJPATH=%s",
667 -rc, HOST_STATE_MANAGER_ROOT));
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500668 return rc;
669 }
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530670
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500671 // Convert to string equivalent of the passed in transition enum.
672 auto request = State::convertForMessage(transition);
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530673
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500674 rc = sd_bus_call_method(bus_type, // On the system bus
675 busname, // Service to contact
676 HOST_STATE_MANAGER_ROOT, // Object path
677 DBUS_PROPERTY_IFACE, // Interface name
678 "Set", // Method to be called
679 &bus_error, // object to return error
680 nullptr, // Response buffer if any
681 "ssv", // Takes 3 arguments
682 HOST_STATE_MANAGER_IFACE,
683 PROPERTY,
684 "s", request.c_str());
685 if(rc < 0)
686 {
687 log<level::ERR>("Failed to initiate transition",
Aditya Saripalli5fb14602017-11-09 14:46:27 +0530688 entry("ERRNO=0x%X, REQUEST=%s", -rc, request.c_str()));
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500689 }
690 else
691 {
692 log<level::INFO>("Transition request initiated successfully");
693 }
vishwa36993272015-11-20 12:43:49 -0600694
695 sd_bus_error_free(&bus_error);
Sergey Solomineb9b8142016-08-23 09:07:28 -0500696 free(busname);
vishwa36993272015-11-20 12:43:49 -0600697
Sergey Solomineb9b8142016-08-23 09:07:28 -0500698 return rc;
vishwa36993272015-11-20 12:43:49 -0600699}
700
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500701namespace power_policy
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500702{
Nan Lifdd8ec52016-08-28 03:57:40 +0800703
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500704using namespace sdbusplus::xyz::openbmc_project::Control::Power::server;
705using IpmiValue = uint8_t;
706using DbusValue = RestorePolicy::Policy;
Nan Lifdd8ec52016-08-28 03:57:40 +0800707
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500708std::map<DbusValue, IpmiValue> dbusToIpmi =
709{
710 {RestorePolicy::Policy::AlwaysOff, 0x00},
711 {RestorePolicy::Policy::Restore, 0x01},
712 {RestorePolicy::Policy::AlwaysOn, 0x02}
713};
Nan Lifdd8ec52016-08-28 03:57:40 +0800714
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500715} // namespace power_policy
Nan Lifdd8ec52016-08-28 03:57:40 +0800716
717//----------------------------------------------------------------------
718// Get Chassis Status commands
719//----------------------------------------------------------------------
720ipmi_ret_t ipmi_get_chassis_status(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500721 ipmi_request_t request,
722 ipmi_response_t response,
723 ipmi_data_len_t data_len,
724 ipmi_context_t context)
Nan Lifdd8ec52016-08-28 03:57:40 +0800725{
726 const char *objname = "/org/openbmc/control/power0";
727 const char *intf = "org.openbmc.control.Power";
728
729 sd_bus *bus = NULL;
730 sd_bus_message *reply = NULL;
731 int r = 0;
732 int pgood = 0;
733 char *busname = NULL;
734 ipmi_ret_t rc = IPMI_CC_OK;
735 ipmi_get_chassis_status_t chassis_status{};
736
Nan Lifdd8ec52016-08-28 03:57:40 +0800737 uint8_t s = 0;
738
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500739 using namespace chassis::internal;
740 using namespace chassis::internal::cache;
741 using namespace power_policy;
742
Deepak Kodihallie6027092017-08-27 08:13:37 -0500743 const auto& powerRestoreSetting = objects.map.at(powerRestoreIntf).front();
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500744 auto method =
745 dbus.new_method_call(
746 objects.service(powerRestoreSetting, powerRestoreIntf).c_str(),
747 powerRestoreSetting.c_str(),
Ratan Guptacc8feb42017-07-25 21:52:10 +0530748 ipmi::PROP_INTF,
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500749 "Get");
750 method.append(powerRestoreIntf, "PowerRestorePolicy");
751 auto resp = dbus.call(method);
752 if (resp.is_method_error())
753 {
754 log<level::ERR>("Error in PowerRestorePolicy Get");
755 report<InternalFailure>();
756 *data_len = 0;
757 return IPMI_CC_UNSPECIFIED_ERROR;
758 }
759 sdbusplus::message::variant<std::string> result;
760 resp.read(result);
761 auto powerRestore =
762 RestorePolicy::convertPolicyFromString(result.get<std::string>());
Nan Lifdd8ec52016-08-28 03:57:40 +0800763
764 *data_len = 4;
765
Tom Joseph63a00512017-08-09 23:39:59 +0530766 bus = ipmid_get_sd_bus_connection();
767
Nan Lifdd8ec52016-08-28 03:57:40 +0800768 r = mapper_get_service(bus, objname, &busname);
769 if (r < 0) {
Aditya Saripalli5fb14602017-11-09 14:46:27 +0530770 log<level::ERR>("Failed to get bus name",
771 entry("ERRNO=0x%X", -r));
Nan Lifdd8ec52016-08-28 03:57:40 +0800772 rc = IPMI_CC_UNSPECIFIED_ERROR;
773 goto finish;
774 }
775
776 r = sd_bus_get_property(bus, busname, objname, intf, "pgood", NULL, &reply, "i");
777 if (r < 0) {
Aditya Saripalli5fb14602017-11-09 14:46:27 +0530778 log<level::ERR>("Failed to call sd_bus_get_property",
779 entry("PROPERTY=%s","pgood"),
780 entry("ERRNO=0x%X", -r),
781 entry("BUS=%s", busname),
782 entry("PATH=%s", objname),
783 entry("INTERFACE=%s", intf));
Nan Lifdd8ec52016-08-28 03:57:40 +0800784 rc = IPMI_CC_UNSPECIFIED_ERROR;
785 goto finish;
786 }
787
788 r = sd_bus_message_read(reply, "i", &pgood);
789 if (r < 0) {
Aditya Saripalli5fb14602017-11-09 14:46:27 +0530790 log<level::ERR>("Failed to read sensor:",
791 entry("ERRNO=0x%X", -r));
Nan Lifdd8ec52016-08-28 03:57:40 +0800792 rc = IPMI_CC_UNSPECIFIED_ERROR;
793 goto finish;
794 }
795
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500796 s = dbusToIpmi.at(powerRestore);
Nan Lifdd8ec52016-08-28 03:57:40 +0800797
798 // Current Power State
799 // [7] reserved
800 // [6..5] power restore policy
801 // 00b = chassis stays powered off after AC/mains returns
802 // 01b = after AC returns, power is restored to the state that was
803 // in effect when AC/mains was lost.
804 // 10b = chassis always powers up after AC/mains returns
805 // 11b = unknow
806 // Set to 00b, by observing the hardware behavior.
807 // Do we need to define a dbus property to identify the restore policy?
808
809 // [4] power control fault
810 // 1b = controller attempted to turn system power on or off, but
811 // system did not enter desired state.
812 // Set to 0b, since We don't support it..
813
814 // [3] power fault
815 // 1b = fault detected in main power subsystem.
816 // set to 0b. for we don't support it.
817
818 // [2] 1b = interlock (chassis is presently shut down because a chassis
819 // panel interlock switch is active). (IPMI 1.5)
820 // set to 0b, for we don't support it.
821
822 // [1] power overload
823 // 1b = system shutdown because of power overload condition.
824 // set to 0b, for we don't support it.
825
826 // [0] power is on
827 // 1b = system power is on
828 // 0b = system power is off(soft-off S4/S5, or mechanical off)
829
830 chassis_status.cur_power_state = ((s & 0x3)<<5) | (pgood & 0x1);
831
832 // Last Power Event
833 // [7..5] – reserved
834 // [4] – 1b = last ‘Power is on’ state was entered via IPMI command
835 // [3] – 1b = last power down caused by power fault
836 // [2] – 1b = last power down caused by a power interlock being activated
837 // [1] – 1b = last power down caused by a Power overload
838 // [0] – 1b = AC failed
839 // set to 0x0, for we don't support these fields.
840
841 chassis_status.last_power_event = 0;
842
843 // Misc. Chassis State
844 // [7] – reserved
845 // [6] – 1b = Chassis Identify command and state info supported (Optional)
846 // 0b = Chassis Identify command support unspecified via this command.
847 // (The Get Command Support command , if implemented, would still
848 // indicate support for the Chassis Identify command)
849 // [5..4] – Chassis Identify State. Mandatory when bit[6] =1b, reserved (return
850 // as 00b) otherwise. Returns the present chassis identify state.
851 // Refer to the Chassis Identify command for more info.
852 // 00b = chassis identify state = Off
853 // 01b = chassis identify state = Temporary(timed) On
854 // 10b = chassis identify state = Indefinite On
855 // 11b = reserved
856 // [3] – 1b = Cooling/fan fault detected
857 // [2] – 1b = Drive Fault
858 // [1] – 1b = Front Panel Lockout active (power off and reset via chassis
859 // push-buttons disabled.)
860 // [0] – 1b = Chassis Intrusion active
861 // set to 0, for we don't support them.
862 chassis_status.misc_power_state = 0;
863
864 // Front Panel Button Capabilities and disable/enable status(Optional)
865 // set to 0, for we don't support them.
866 chassis_status.front_panel_button_cap_status = 0;
867
868 // Pack the actual response
869 memcpy(response, &chassis_status, *data_len);
870
871finish:
872 free(busname);
873 reply = sd_bus_message_unref(reply);
874
875 return rc;
876}
Chris Austen7888c4d2015-12-03 15:26:20 -0600877
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +0530878//-------------------------------------------------------------
879// Send a command to SoftPowerOff application to stop any timer
880//-------------------------------------------------------------
881int stop_soft_off_timer()
882{
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +0530883 constexpr auto iface = "org.freedesktop.DBus.Properties";
884 constexpr auto soft_off_iface = "xyz.openbmc_project.Ipmi.Internal."
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500885 "SoftPowerOff";
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +0530886
887 constexpr auto property = "ResponseReceived";
888 constexpr auto value = "xyz.openbmc_project.Ipmi.Internal."
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500889 "SoftPowerOff.HostResponse.HostShutdown";
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +0530890
891 // Get the system bus where most system services are provided.
892 auto bus = ipmid_get_sd_bus_connection();
893
894 // Get the service name
Andrew Geissler2b4e4592017-06-08 11:18:35 -0500895 // TODO openbmc/openbmc#1661 - Mapper refactor
896 //
897 // See openbmc/openbmc#1743 for some details but high level summary is that
898 // for now the code will directly call the soft off interface due to a
899 // race condition with mapper usage
900 //
901 //char *busname = nullptr;
902 //auto r = mapper_get_service(bus, SOFTOFF_OBJPATH, &busname);
903 //if (r < 0)
904 //{
905 // fprintf(stderr, "Failed to get %s bus name: %s\n",
Aditya Saripalli5fb14602017-11-09 14:46:27 +0530906 // SOFTOFF_OBJPATH, -r);
Andrew Geissler2b4e4592017-06-08 11:18:35 -0500907 // return r;
908 //}
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +0530909
910 // No error object or reply expected.
Andrew Geissler2b4e4592017-06-08 11:18:35 -0500911 int rc = sd_bus_call_method(bus, SOFTOFF_BUSNAME, SOFTOFF_OBJPATH, iface,
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500912 "Set", nullptr, nullptr, "ssv",
913 soft_off_iface, property, "s", value);
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +0530914 if (rc < 0)
915 {
Aditya Saripalli5fb14602017-11-09 14:46:27 +0530916 log<level::ERR>("Failed to set property in SoftPowerOff object",
917 entry("ERRNO=0x%X", -rc));
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +0530918 }
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500919
Andrew Geissler2b4e4592017-06-08 11:18:35 -0500920 //TODO openbmc/openbmc#1661 - Mapper refactor
921 //free(busname);
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +0530922 return rc;
923}
924
vishwa36993272015-11-20 12:43:49 -0600925//----------------------------------------------------------------------
Andrew Geisslera6e3a302017-05-31 19:34:00 -0500926// Create file to indicate there is no need for softoff notification to host
927//----------------------------------------------------------------------
928void indicate_no_softoff_needed()
929{
930 fs::path path{HOST_INBAND_REQUEST_DIR};
931 if (!fs::is_directory(path))
932 {
933 fs::create_directory(path);
934 }
935
936 // Add the host instance (default 0 for now) to the file name
937 std::string file{HOST_INBAND_REQUEST_FILE};
938 auto size = std::snprintf(nullptr,0,file.c_str(),0);
939 size++; // null
940 std::unique_ptr<char[]> buf(new char[size]);
941 std::snprintf(buf.get(),size,file.c_str(),0);
942
943 // Append file name to directory and create it
944 path /= buf.get();
945 std::ofstream(path.c_str());
946}
947
948//----------------------------------------------------------------------
vishwa36993272015-11-20 12:43:49 -0600949// Chassis Control commands
950//----------------------------------------------------------------------
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500951ipmi_ret_t ipmi_chassis_control(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
952 ipmi_request_t request,
953 ipmi_response_t response,
954 ipmi_data_len_t data_len,
955 ipmi_context_t context)
vishwa36993272015-11-20 12:43:49 -0600956{
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500957 // Error from power off.
958 int rc = 0;
vishwa36993272015-11-20 12:43:49 -0600959
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500960 // No response for this command.
vishwa36993272015-11-20 12:43:49 -0600961 *data_len = 0;
962
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500963 // Catch the actual operaton by peeking into request buffer
964 uint8_t chassis_ctrl_cmd = *(uint8_t *)request;
vishwa36993272015-11-20 12:43:49 -0600965
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500966 switch(chassis_ctrl_cmd)
967 {
968 case CMD_POWER_ON:
969 rc = initiate_state_transition(State::Host::Transition::On);
970 break;
971 case CMD_POWER_OFF:
Vishwanatha Subbanna8b26d352017-08-04 18:35:18 +0530972 // This path would be hit in 2 conditions.
973 // 1: When user asks for power off using ipmi chassis command 0x04
974 // 2: Host asking for power off post shutting down.
975
976 // If it's a host requested power off, then need to nudge Softoff
977 // application that it needs to stop the watchdog timer if running.
978 // If it is a user requested power off, then this is not really
979 // needed. But then we need to differentiate between user and host
980 // calling this same command
981
982 // For now, we are going ahead with trying to nudge the soft off and
983 // interpret the failure to do so as a non softoff case
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500984 rc = stop_soft_off_timer();
Vishwanatha Subbanna8b26d352017-08-04 18:35:18 +0530985
Andrew Geisslera6e3a302017-05-31 19:34:00 -0500986 // Only request the Off transition if the soft power off
987 // application is not running
988 if (rc < 0)
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500989 {
Andrew Geisslera6e3a302017-05-31 19:34:00 -0500990 // First create a file to indicate to the soft off application
Vishwanatha Subbanna8b26d352017-08-04 18:35:18 +0530991 // that it should not run. Not doing this will result in State
992 // manager doing a default soft power off when asked for power
993 // off.
Andrew Geisslera6e3a302017-05-31 19:34:00 -0500994 indicate_no_softoff_needed();
995
996 // Now request the shutdown
997 rc = initiate_state_transition(State::Host::Transition::Off);
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500998 }
Andrew Geisslera6e3a302017-05-31 19:34:00 -0500999 else
1000 {
Vishwanatha Subbanna8b26d352017-08-04 18:35:18 +05301001 log<level::INFO>("Soft off is running, so let shutdown target "
1002 "stop the host");
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001003 }
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001004 break;
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +05301005
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001006 case CMD_HARD_RESET:
1007 case CMD_POWER_CYCLE:
1008 // SPEC has a section that says certain implementations can trigger
1009 // PowerOn if power is Off when a command to power cycle is
1010 // requested
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001011
1012 // First create a file to indicate to the soft off application
1013 // that it should not run since this is a direct user initiated
1014 // power reboot request (i.e. a reboot request that is not
1015 // originating via a soft power off SMS request)
1016 indicate_no_softoff_needed();
1017
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001018 rc = initiate_state_transition(State::Host::Transition::Reboot);
1019 break;
Vishwanatha Subbanna8b26d352017-08-04 18:35:18 +05301020
1021 case CMD_SOFT_OFF_VIA_OVER_TEMP:
1022 // Request Host State Manager to do a soft power off
1023 rc = initiate_state_transition(State::Host::Transition::Off);
1024 break;
1025
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001026 default:
1027 {
Aditya Saripalli5fb14602017-11-09 14:46:27 +05301028 log<level::ERR>("Invalid Chassis Control command",
1029 entry("CMD=0x%X", chassis_ctrl_cmd));
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001030 rc = -1;
1031 }
1032 }
vishwa36993272015-11-20 12:43:49 -06001033
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001034 return ( (rc < 0) ? IPMI_CC_INVALID : IPMI_CC_OK);
vishwa36993272015-11-20 12:43:49 -06001035}
1036
Tom Joseph5110c122018-03-23 17:55:40 +05301037ipmi_ret_t ipmi_chassis_identify(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1038 ipmi_request_t request,
1039 ipmi_response_t response,
1040 ipmi_data_len_t data_len,
1041 ipmi_context_t context)
1042{
1043 static std::atomic_size_t currentCallerId(0);
1044 static std::unique_ptr<std::future<void>> future;
1045 static std::condition_variable condition;
1046 static std::mutex timeoutMutex;
1047
1048 if (*data_len > 2)
1049 {
1050 return IPMI_CC_REQ_DATA_LEN_INVALID;
1051 }
1052 uint8_t identifyInterval = *data_len > 0 ?
1053 (static_cast<uint8_t*>(request))[0] :
1054 DEFAULT_IDENTIFY_TIME_OUT;
1055 bool forceIdentify =
1056 *data_len == 2 ? (static_cast<uint8_t*>(request))[1] & 0x01 : false;
1057
1058 currentCallerId++;
1059
1060 // stop any threads currently running
1061 condition.notify_all();
1062
1063 // lookup enclosure_identify group owner(s) in mapper
1064 auto mapperCall = chassis::internal::dbus.new_method_call(
1065 ipmi::MAPPER_BUS_NAME,
1066 ipmi::MAPPER_OBJ,
1067 ipmi::MAPPER_INTF,
1068 "GetObject");
1069
1070 mapperCall.append(identify_led_object_name);
1071 static const std::vector<std::string> interfaces =
1072 {
1073 "xyz.openbmc_project.Led.Group"
1074 };
1075 mapperCall.append(interfaces);
1076 auto mapperReply = chassis::internal::dbus.call(mapperCall);
1077 if (mapperReply.is_method_error())
1078 {
1079 log<level::ERR>("Chassis Identify: Error communicating to mapper.");
1080 return IPMI_CC_RESPONSE_ERROR;
1081 }
1082 std::vector<std::pair<std::string, std::vector<std::string>>> mapperResp;
1083 mapperReply.read(mapperResp);
1084
1085 for (auto& object : mapperResp)
1086 {
1087 std::string& connection = object.first;
1088
1089 if (identifyInterval || forceIdentify)
1090 {
1091 auto ledOn = chassis::internal::dbus.new_method_call(
1092 connection.c_str(),
1093 identify_led_object_name,
1094 "org.freedesktop.DBus.Properties", "Set");
1095 ledOn.append(
1096 "xyz.openbmc_project.Led.Group", "Asserted",
1097 sdbusplus::message::variant<bool>(
1098 true));
1099 auto ledReply = chassis::internal::dbus.call(ledOn);
1100 if (ledReply.is_method_error())
1101 {
1102 log<level::ERR>("Chassis Identify: Error Setting State On\n");
1103 return IPMI_CC_RESPONSE_ERROR;
1104 }
1105 if (forceIdentify)
1106 {
1107 return IPMI_CC_OK;
1108 }
1109 }
1110
1111 size_t threadCallerId = currentCallerId;
1112 future = std::make_unique<std::future<void>>(
1113 std::async(std::launch::async,
1114 [connection,
1115 identifyInterval,
1116 threadCallerId]
1117 {
1118 std::unique_lock<std::mutex> lock(timeoutMutex);
1119 if (condition.wait_for(lock,
1120 std::chrono::seconds(identifyInterval),
1121 [&threadCallerId]{return currentCallerId != threadCallerId;}))
1122 {
1123 return; // another thread started.
1124 }
1125 auto ledOff = chassis::internal::dbus.new_method_call(
1126 connection.c_str(),
1127 identify_led_object_name,
1128 "org.freedesktop.DBus.Properties", "Set");
1129 ledOff.append("xyz.openbmc_project.Led.Group", "Asserted",
1130 sdbusplus::message::variant<bool>(
1131 false));
1132 auto ledReply = chassis::internal::dbus.call(ledOff);
1133 if (ledReply.is_method_error())
1134 {
1135 log<level::ERR>("Chassis Identify: Error Setting State Off\n");
1136 }
1137 }));
1138 }
1139 return IPMI_CC_OK;
1140}
1141
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001142namespace boot_options
1143{
1144
1145using namespace sdbusplus::xyz::openbmc_project::Control::Boot::server;
1146using IpmiValue = uint8_t;
1147constexpr auto ipmiDefault = 0;
1148
1149std::map<IpmiValue, Source::Sources> sourceIpmiToDbus =
1150{
1151 {0x01, Source::Sources::Network},
1152 {0x02, Source::Sources::Disk},
1153 {0x05, Source::Sources::ExternalMedia},
1154 {ipmiDefault, Source::Sources::Default}
shgoupfd84fbbf2015-12-17 10:05:51 +08001155};
1156
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001157std::map<IpmiValue, Mode::Modes> modeIpmiToDbus =
1158{
1159 {0x03, Mode::Modes::Safe},
1160 {0x06, Mode::Modes::Setup},
1161 {ipmiDefault, Mode::Modes::Regular}
shgoupfd84fbbf2015-12-17 10:05:51 +08001162};
1163
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001164std::map<Source::Sources, IpmiValue> sourceDbusToIpmi =
1165{
1166 {Source::Sources::Network, 0x01},
1167 {Source::Sources::Disk, 0x02},
1168 {Source::Sources::ExternalMedia, 0x05},
1169 {Source::Sources::Default, ipmiDefault}
1170};
shgoupfd84fbbf2015-12-17 10:05:51 +08001171
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001172std::map<Mode::Modes, IpmiValue> modeDbusToIpmi =
1173{
1174 {Mode::Modes::Safe, 0x03},
1175 {Mode::Modes::Setup, 0x06},
1176 {Mode::Modes::Regular, ipmiDefault}
1177};
shgoupfd84fbbf2015-12-17 10:05:51 +08001178
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001179} // namespace boot_options
shgoupfd84fbbf2015-12-17 10:05:51 +08001180
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001181ipmi_ret_t ipmi_chassis_get_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1182 ipmi_request_t request,
1183 ipmi_response_t response,
1184 ipmi_data_len_t data_len,
1185 ipmi_context_t context)
Adriana Kobylak40814c62015-10-27 15:58:44 -05001186{
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001187 using namespace boot_options;
shgoupfd84fbbf2015-12-17 10:05:51 +08001188 ipmi_ret_t rc = IPMI_CC_PARM_NOT_SUPPORTED;
1189 char *p = NULL;
1190 get_sys_boot_options_response_t *resp = (get_sys_boot_options_response_t *) response;
1191 get_sys_boot_options_t *reqptr = (get_sys_boot_options_t*) request;
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001192 IpmiValue bootOption = ipmiDefault;
Adriana Kobylak40814c62015-10-27 15:58:44 -05001193
shgoupfd84fbbf2015-12-17 10:05:51 +08001194 memset(resp,0,sizeof(*resp));
1195 resp->version = SET_PARM_VERSION;
1196 resp->parm = 5;
ratagupta6f6bff2016-04-04 06:20:11 -05001197 resp->data[0] = SET_PARM_BOOT_FLAGS_VALID_ONE_TIME;
Adriana Kobylak40814c62015-10-27 15:58:44 -05001198
Adriana Kobylak40814c62015-10-27 15:58:44 -05001199
shgoupfd84fbbf2015-12-17 10:05:51 +08001200 /*
1201 * Parameter #5 means boot flags. Please refer to 28.13 of ipmi doc.
1202 * This is the only parameter used by petitboot.
1203 */
Ratan Guptafd28dd72016-08-01 04:58:01 -05001204 if ( reqptr->parameter == static_cast<uint8_t>
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001205 ( BootOptionParameter::BOOT_FLAGS )) {
shgoupfd84fbbf2015-12-17 10:05:51 +08001206
Ratan Guptafd28dd72016-08-01 04:58:01 -05001207 *data_len = static_cast<uint8_t>(BootOptionResponseSize::BOOT_FLAGS);
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001208 using namespace chassis::internal;
1209 using namespace chassis::internal::cache;
shgoupfd84fbbf2015-12-17 10:05:51 +08001210
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001211 try
ratagupta6f6bff2016-04-04 06:20:11 -05001212 {
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001213 auto bootSetting = settings::boot::setting(objects, bootSourceIntf);
1214 const auto& bootSourceSetting =
1215 std::get<settings::Path>(bootSetting);
1216 auto oneTimeEnabled =
1217 std::get<settings::boot::OneTimeEnabled>(bootSetting);
1218 auto method =
1219 dbus.new_method_call(
1220 objects.service(bootSourceSetting, bootSourceIntf).c_str(),
1221 bootSourceSetting.c_str(),
1222 ipmi::PROP_INTF,
1223 "Get");
1224 method.append(bootSourceIntf, "BootSource");
1225 auto reply = dbus.call(method);
1226 if (reply.is_method_error())
1227 {
1228 log<level::ERR>("Error in BootSource Get");
1229 report<InternalFailure>();
1230 *data_len = 0;
1231 return IPMI_CC_UNSPECIFIED_ERROR;
1232 }
1233 sdbusplus::message::variant<std::string> result;
1234 reply.read(result);
1235 auto bootSource =
1236 Source::convertSourcesFromString(result.get<std::string>());
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001237
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001238 bootSetting = settings::boot::setting(objects, bootModeIntf);
1239 const auto& bootModeSetting = std::get<settings::Path>(bootSetting);
1240 method = dbus.new_method_call(
1241 objects.service(bootModeSetting, bootModeIntf).
1242 c_str(),
1243 bootModeSetting.c_str(),
1244 ipmi::PROP_INTF,
1245 "Get");
1246 method.append(bootModeIntf, "BootMode");
1247 reply = dbus.call(method);
1248 if (reply.is_method_error())
1249 {
1250 log<level::ERR>("Error in BootMode Get");
1251 report<InternalFailure>();
1252 *data_len = 0;
1253 return IPMI_CC_UNSPECIFIED_ERROR;
1254 }
1255 reply.read(result);
1256 auto bootMode =
1257 Mode::convertModesFromString(result.get<std::string>());
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001258
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001259 bootOption = sourceDbusToIpmi.at(bootSource);
1260 if ((Mode::Modes::Regular == bootMode) &&
1261 (Source::Sources::Default == bootSource))
1262 {
1263 bootOption = ipmiDefault;
1264 }
1265 else if (Source::Sources::Default == bootSource)
1266 {
1267 bootOption = modeDbusToIpmi.at(bootMode);
1268 }
1269 resp->data[1] = (bootOption << 2);
ratagupta6f6bff2016-04-04 06:20:11 -05001270
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001271 resp->data[0] = oneTimeEnabled ?
1272 SET_PARM_BOOT_FLAGS_VALID_ONE_TIME:
1273 SET_PARM_BOOT_FLAGS_VALID_PERMANENT;
ratagupta6f6bff2016-04-04 06:20:11 -05001274
ratagupta6f6bff2016-04-04 06:20:11 -05001275 rc = IPMI_CC_OK;
ratagupta6f6bff2016-04-04 06:20:11 -05001276 }
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001277 catch (InternalFailure& e)
1278 {
1279 report<InternalFailure>();
1280 *data_len = 0;
1281 return IPMI_CC_UNSPECIFIED_ERROR;
1282 }
Ratan Guptafd28dd72016-08-01 04:58:01 -05001283 } else if ( reqptr->parameter == static_cast<uint8_t>
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001284 ( BootOptionParameter::OPAL_NETWORK_SETTINGS )) {
Ratan Guptafd28dd72016-08-01 04:58:01 -05001285
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001286 *data_len = static_cast<uint8_t>(BootOptionResponseSize::OPAL_NETWORK_SETTINGS);
Ratan Guptafd28dd72016-08-01 04:58:01 -05001287
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001288 resp->parm = static_cast<uint8_t>(BootOptionParameter::OPAL_NETWORK_SETTINGS);
Ratan Guptafd28dd72016-08-01 04:58:01 -05001289
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001290 int ret = getHostNetworkData(resp);
Ratan Guptafd28dd72016-08-01 04:58:01 -05001291
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001292 if (ret < 0) {
Ratan Guptafd28dd72016-08-01 04:58:01 -05001293
Aditya Saripalli5fb14602017-11-09 14:46:27 +05301294 log<level::ERR>(
1295 "getHostNetworkData failed for get_sys_boot_options.");
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001296 rc = IPMI_CC_UNSPECIFIED_ERROR;
Ratan Guptafd28dd72016-08-01 04:58:01 -05001297
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001298 }else
1299 rc = IPMI_CC_OK;
Ratan Guptafd28dd72016-08-01 04:58:01 -05001300 }
1301
1302 else {
Aditya Saripalli5fb14602017-11-09 14:46:27 +05301303 log<level::ERR>("Unsupported parameter", entry(
1304 "PARAM=0x%x", reqptr->parameter));
shgoupfd84fbbf2015-12-17 10:05:51 +08001305 }
1306
1307 if (p)
1308 free(p);
1309
Ratan Guptafd28dd72016-08-01 04:58:01 -05001310 if (rc == IPMI_CC_OK)
1311 {
1312 *data_len += 2;
1313 }
1314
shgoupfd84fbbf2015-12-17 10:05:51 +08001315 return rc;
1316}
1317
1318
1319
1320ipmi_ret_t ipmi_chassis_set_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001321 ipmi_request_t request,
1322 ipmi_response_t response,
1323 ipmi_data_len_t data_len,
1324 ipmi_context_t context)
shgoupfd84fbbf2015-12-17 10:05:51 +08001325{
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001326 using namespace boot_options;
shgoupfd84fbbf2015-12-17 10:05:51 +08001327 ipmi_ret_t rc = IPMI_CC_OK;
shgoupfd84fbbf2015-12-17 10:05:51 +08001328 set_sys_boot_options_t *reqptr = (set_sys_boot_options_t *) request;
1329
Ratan Guptafd28dd72016-08-01 04:58:01 -05001330 printf("IPMI SET_SYS_BOOT_OPTIONS reqptr->parameter =[%d]\n",reqptr->parameter);
1331
shgoupfd84fbbf2015-12-17 10:05:51 +08001332 // This IPMI command does not have any resposne data
1333 *data_len = 0;
1334
1335 /* 000101
1336 * Parameter #5 means boot flags. Please refer to 28.13 of ipmi doc.
1337 * This is the only parameter used by petitboot.
1338 */
Ratan Guptafd28dd72016-08-01 04:58:01 -05001339
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001340 if (reqptr->parameter == (uint8_t)BootOptionParameter::BOOT_FLAGS)
1341 {
1342 IpmiValue bootOption = ((reqptr->data[1] & 0x3C) >> 2);
1343 using namespace chassis::internal;
1344 using namespace chassis::internal::cache;
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001345 auto oneTimeEnabled = false;
1346 constexpr auto enabledIntf = "xyz.openbmc_project.Object.Enable";
Tom Joseph57e8eb72017-09-25 18:05:02 +05301347 constexpr auto oneTimePath =
1348 "/xyz/openbmc_project/control/host0/boot/one_time";
shgoupfd84fbbf2015-12-17 10:05:51 +08001349
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001350 try
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001351 {
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001352 bool permanent =
1353 (reqptr->data[0] & SET_PARM_BOOT_FLAGS_PERMANENT) ==
1354 SET_PARM_BOOT_FLAGS_PERMANENT;
1355
Tom Joseph57e8eb72017-09-25 18:05:02 +05301356 auto bootSetting =
1357 settings::boot::setting(objects, bootSourceIntf);
1358
1359 oneTimeEnabled =
1360 std::get<settings::boot::OneTimeEnabled>(bootSetting);
1361
1362 /*
1363 * Check if the current boot setting is onetime or permanent, if the
1364 * request in the command is otherwise, then set the "Enabled"
1365 * property in one_time object path to 'True' to indicate onetime
1366 * and 'False' to indicate permanent.
1367 *
1368 * Once the onetime/permanent setting is applied, then the bootMode
1369 * and bootSource is updated for the corresponding object.
1370 */
1371 if ((permanent && oneTimeEnabled) ||
1372 (!permanent && !oneTimeEnabled))
1373 {
1374 auto service = ipmi::getService(dbus, enabledIntf, oneTimePath);
1375
1376 ipmi::setDbusProperty(dbus,
1377 service,
1378 oneTimePath,
1379 enabledIntf,
1380 "Enabled",
1381 !permanent);
1382 }
1383
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001384 auto modeItr = modeIpmiToDbus.find(bootOption);
1385 auto sourceItr = sourceIpmiToDbus.find(bootOption);
1386 if (sourceIpmiToDbus.end() != sourceItr)
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001387 {
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001388 sdbusplus::message::variant<std::string> property =
1389 convertForMessage(sourceItr->second);
Tom Joseph57e8eb72017-09-25 18:05:02 +05301390 auto bootSetting = settings::boot::setting(objects,
1391 bootSourceIntf);
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001392 const auto& bootSourceSetting =
1393 std::get<settings::Path>(bootSetting);
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001394 auto method =
1395 dbus.new_method_call(
1396 objects.service(bootSourceSetting, bootSourceIntf).
1397 c_str(),
1398 bootSourceSetting.c_str(),
1399 ipmi::PROP_INTF,
1400 "Set");
1401 method.append(bootSourceIntf, "BootSource", property);
1402 auto reply = dbus.call(method);
1403 if (reply.is_method_error())
1404 {
1405 log<level::ERR>("Error in BootSource Set");
1406 report<InternalFailure>();
1407 *data_len = 0;
1408 return IPMI_CC_UNSPECIFIED_ERROR;
1409 }
1410
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001411 }
1412 if (modeIpmiToDbus.end() != modeItr)
1413 {
1414 sdbusplus::message::variant<std::string> property =
1415 convertForMessage(modeItr->second);
Tom Joseph57e8eb72017-09-25 18:05:02 +05301416 auto bootSetting = settings::boot::setting(objects,
1417 bootModeIntf);
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001418 const auto& bootModeSetting =
1419 std::get<settings::Path>(bootSetting);
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001420 auto method =
1421 dbus.new_method_call(
1422 objects.service(bootModeSetting, bootModeIntf).c_str(),
1423 bootModeSetting.c_str(),
1424 ipmi::PROP_INTF,
1425 "Set");
1426 method.append(bootModeIntf, "BootMode", property);
1427 auto reply = dbus.call(method);
1428 if (reply.is_method_error())
1429 {
1430 log<level::ERR>("Error in BootMode Set");
1431 report<InternalFailure>();
1432 *data_len = 0;
1433 return IPMI_CC_UNSPECIFIED_ERROR;
1434 }
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001435 }
1436 }
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001437 catch (InternalFailure& e)
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001438 {
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001439 report<InternalFailure>();
1440 *data_len = 0;
1441 return IPMI_CC_UNSPECIFIED_ERROR;
shgoupfd84fbbf2015-12-17 10:05:51 +08001442 }
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001443 } else if (reqptr->parameter ==
1444 (uint8_t)BootOptionParameter::OPAL_NETWORK_SETTINGS) {
Ratan Guptafd28dd72016-08-01 04:58:01 -05001445
1446 int ret = setHostNetworkData(reqptr);
1447 if (ret < 0) {
Aditya Saripalli5fb14602017-11-09 14:46:27 +05301448 log<level::ERR>(
1449 "setHostNetworkData failed for set_sys_boot_options");
Ratan Guptafd28dd72016-08-01 04:58:01 -05001450 rc = IPMI_CC_UNSPECIFIED_ERROR;
1451 }
Tom Josephf536c902017-09-25 18:08:15 +05301452 } else if (reqptr->parameter ==
1453 static_cast<uint8_t>(BootOptionParameter::BOOT_INFO)) {
1454 // Handle parameter #4 and return command completed normally
1455 // (IPMI_CC_OK). There is no implementation in OpenBMC for this
1456 // parameter. This is added to support the ipmitool command `chassis
1457 // bootdev` which sends set on parameter #4, before setting the boot
1458 // flags.
1459 rc = IPMI_CC_OK;
1460 } else {
Aditya Saripalli5fb14602017-11-09 14:46:27 +05301461 log<level::ERR>("Unsupported parameter", entry(
1462 "PARAM=0x%x", reqptr->parameter));
shgoupfd84fbbf2015-12-17 10:05:51 +08001463 rc = IPMI_CC_PARM_NOT_SUPPORTED;
Adriana Kobylak40814c62015-10-27 15:58:44 -05001464 }
1465
1466 return rc;
1467}
1468
1469void register_netfn_chassis_functions()
1470{
Tom05732372016-09-06 17:21:23 +05301471 // <Wildcard Command>
Tom05732372016-09-06 17:21:23 +05301472 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_WILDCARD, NULL, ipmi_chassis_wildcard,
1473 PRIVILEGE_USER);
Adriana Kobylak40814c62015-10-27 15:58:44 -05001474
Tom05732372016-09-06 17:21:23 +05301475 // Get Chassis Capabilities
Tom05732372016-09-06 17:21:23 +05301476 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_GET_CHASSIS_CAP, NULL, ipmi_get_chassis_cap,
1477 PRIVILEGE_USER);
Nan Li8d15fb42016-08-16 22:29:40 +08001478
Tom05732372016-09-06 17:21:23 +05301479 // <Get System Boot Options>
Tom05732372016-09-06 17:21:23 +05301480 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_GET_SYS_BOOT_OPTIONS, NULL,
1481 ipmi_chassis_get_sys_boot_options, PRIVILEGE_OPERATOR);
Adriana Kobylak40814c62015-10-27 15:58:44 -05001482
Tom05732372016-09-06 17:21:23 +05301483 // <Get Chassis Status>
Tom05732372016-09-06 17:21:23 +05301484 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_CHASSIS_STATUS, NULL, ipmi_get_chassis_status,
1485 PRIVILEGE_USER);
Nan Lifdd8ec52016-08-28 03:57:40 +08001486
Tom05732372016-09-06 17:21:23 +05301487 // <Chassis Control>
Tom05732372016-09-06 17:21:23 +05301488 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_CHASSIS_CONTROL, NULL, ipmi_chassis_control,
1489 PRIVILEGE_OPERATOR);
shgoupfd84fbbf2015-12-17 10:05:51 +08001490
Tom Joseph5110c122018-03-23 17:55:40 +05301491 // <Chassis Identify>
Tom Joseph5110c122018-03-23 17:55:40 +05301492 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>
Tom05732372016-09-06 17:21:23 +05301496 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_SET_SYS_BOOT_OPTIONS, NULL,
1497 ipmi_chassis_set_sys_boot_options, PRIVILEGE_OPERATOR);
vishwa36993272015-11-20 12:43:49 -06001498}