blob: 2e892b91f59d210f8dc0663435c004ceb51fa081 [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>
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -050036#include <xyz/openbmc_project/State/PowerOnHours/server.hpp>
Ratan Guptadcb10672017-07-10 10:33:50 +053037
Vishwanatha Subbannab891a572017-03-31 11:34:48 +053038#include "config.h"
ratagupta6f6bff2016-04-04 06:20:11 -050039
40//Defines
Ratan Guptafd28dd72016-08-01 04:58:01 -050041#define SET_PARM_VERSION 0x01
42#define SET_PARM_BOOT_FLAGS_PERMANENT 0x40 //boot flags data1 7th bit on
ratagupta6f6bff2016-04-04 06:20:11 -050043#define SET_PARM_BOOT_FLAGS_VALID_ONE_TIME 0x80 //boot flags data1 8th bit on
Ratan Guptafd28dd72016-08-01 04:58:01 -050044#define SET_PARM_BOOT_FLAGS_VALID_PERMANENT 0xC0 //boot flags data1 7 & 8 bit on
ratagupta6f6bff2016-04-04 06:20:11 -050045
Ratan Guptafd28dd72016-08-01 04:58:01 -050046constexpr size_t SIZE_MAC = 18;
47constexpr size_t SIZE_BOOT_OPTION = (uint8_t)BootOptionResponseSize::
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -050048 OPAL_NETWORK_SETTINGS;//Maximum size of the boot option parametrs
Ratan Guptafd28dd72016-08-01 04:58:01 -050049constexpr size_t SIZE_PREFIX = 7;
50constexpr size_t MAX_PREFIX_VALUE = 32;
51constexpr size_t SIZE_COOKIE = 4;
52constexpr size_t SIZE_VERSION = 2;
Tom Joseph5110c122018-03-23 17:55:40 +053053constexpr size_t DEFAULT_IDENTIFY_TIME_OUT = 15;
Ratan Gupta6ec7daa2017-07-15 14:13:01 +053054
Ratan Guptafd28dd72016-08-01 04:58:01 -050055//PetiBoot-Specific
Ratan Gupta6ec7daa2017-07-15 14:13:01 +053056static constexpr uint8_t net_conf_initial_bytes[] = {0x80, 0x21, 0x70, 0x62,
57 0x21, 0x00, 0x01, 0x06};
Ratan Guptafd28dd72016-08-01 04:58:01 -050058
59static constexpr size_t COOKIE_OFFSET = 1;
60static constexpr size_t VERSION_OFFSET = 5;
Ratan Gupta6ec7daa2017-07-15 14:13:01 +053061static constexpr size_t ADDR_SIZE_OFFSET = 8;
Ratan Guptafd28dd72016-08-01 04:58:01 -050062static constexpr size_t MAC_OFFSET = 9;
63static constexpr size_t ADDRTYPE_OFFSET = 16;
64static constexpr size_t IPADDR_OFFSET = 17;
ratagupta6f6bff2016-04-04 06:20:11 -050065
shgoupfd84fbbf2015-12-17 10:05:51 +080066
Adriana Kobylak40814c62015-10-27 15:58:44 -050067void register_netfn_chassis_functions() __attribute__((constructor));
68
shgoupfd84fbbf2015-12-17 10:05:51 +080069// Host settings in dbus
70// Service name should be referenced by connection name got via object mapper
71const char *settings_object_name = "/org/openbmc/settings/host0";
72const char *settings_intf_name = "org.freedesktop.DBus.Properties";
73const char *host_intf_name = "org.openbmc.settings.Host";
Tom Joseph5110c122018-03-23 17:55:40 +053074const char *identify_led_object_name =
75 "/xyz/openbmc_project/led/groups/enclosure_identify";
shgoupfd84fbbf2015-12-17 10:05:51 +080076
Ratan Guptadcb10672017-07-10 10:33:50 +053077constexpr auto SETTINGS_ROOT = "/";
78constexpr auto SETTINGS_MATCH = "host0";
Ratan Guptadcb10672017-07-10 10:33:50 +053079
80constexpr auto IP_INTERFACE = "xyz.openbmc_project.Network.IP";
81constexpr auto MAC_INTERFACE = "xyz.openbmc_project.Network.MACAddress";
82
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -050083static constexpr auto chassisStateRoot = "/xyz/openbmc_project/state";
84static constexpr auto chassisPOHStateIntf =
85 "xyz.openbmc_project.State.PowerOnHours";
86static constexpr auto pOHCounterProperty = "POHCounter";
87static constexpr auto match = "chassis0";
Ratan Guptadcb10672017-07-10 10:33:50 +053088
Nan Li8d15fb42016-08-16 22:29:40 +080089typedef struct
90{
91 uint8_t cap_flags;
92 uint8_t fru_info_dev_addr;
93 uint8_t sdr_dev_addr;
94 uint8_t sel_dev_addr;
95 uint8_t system_management_dev_addr;
96 uint8_t bridge_dev_addr;
97}__attribute__((packed)) ipmi_chassis_cap_t;
98
Nan Lifdd8ec52016-08-28 03:57:40 +080099typedef struct
100{
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500101 uint8_t cur_power_state;
102 uint8_t last_power_event;
103 uint8_t misc_power_state;
104 uint8_t front_panel_button_cap_status;
Nan Lifdd8ec52016-08-28 03:57:40 +0800105}__attribute__((packed)) ipmi_get_chassis_status_t;
106
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -0500107/**
108 * @struct Get POH counter command response data
109 */
110struct GetPOHCountResponse
111{
112 uint8_t minPerCount; ///< Minutes per count
113 uint8_t counterReading[4]; ///< Counter reading
114}__attribute__((packed));
115
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530116// Phosphor Host State manager
117namespace State = sdbusplus::xyz::openbmc_project::State::server;
118
Andrew Geisslera6e3a302017-05-31 19:34:00 -0500119namespace fs = std::experimental::filesystem;
120
Ratan Guptadcb10672017-07-10 10:33:50 +0530121using namespace phosphor::logging;
122using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Marri Devender Rao81719702018-05-07 00:53:48 -0500123using namespace sdbusplus::xyz::openbmc_project::Control::Boot::server;
Deepak Kodihalli8cc19362017-07-21 11:18:38 -0500124namespace chassis
125{
126namespace internal
127{
128
129constexpr auto bootModeIntf = "xyz.openbmc_project.Control.Boot.Mode";
130constexpr auto bootSourceIntf = "xyz.openbmc_project.Control.Boot.Source";
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500131constexpr auto powerRestoreIntf =
132 "xyz.openbmc_project.Control.Power.RestorePolicy";
Deepak Kodihalli8cc19362017-07-21 11:18:38 -0500133sdbusplus::bus::bus dbus(ipmid_get_sd_bus_connection());
134
135namespace cache
136{
137
138settings::Objects objects(dbus,
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500139 {bootModeIntf, bootSourceIntf, powerRestoreIntf});
Deepak Kodihalli8cc19362017-07-21 11:18:38 -0500140
141} // namespace cache
142} // namespace internal
143} // namespace chassis
144
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -0500145namespace poh
146{
147
148constexpr auto minutesPerCount = 60;
149
150} // namespace poh
151
Ratan Guptadcb10672017-07-10 10:33:50 +0530152//TODO : Can remove the below function as we have
153// new functions which uses sdbusplus.
154//
155// openbmc/openbmc#1489
ratagupta6f6bff2016-04-04 06:20:11 -0500156int dbus_get_property(const char *name, char **buf)
shgoupfd84fbbf2015-12-17 10:05:51 +0800157{
158 sd_bus_error error = SD_BUS_ERROR_NULL;
159 sd_bus_message *m = NULL;
160 sd_bus *bus = NULL;
161 char *temp_buf = NULL;
162 char *connection = NULL;
163 int r;
164
Brad Bishop35518682016-07-22 08:35:41 -0400165 // Get the system bus where most system services are provided.
166 bus = ipmid_get_sd_bus_connection();
shgoupfd84fbbf2015-12-17 10:05:51 +0800167
Brad Bishop35518682016-07-22 08:35:41 -0400168 r = mapper_get_service(bus, settings_object_name, &connection);
shgoupfd84fbbf2015-12-17 10:05:51 +0800169 if (r < 0) {
Aditya Saripalli5fb14602017-11-09 14:46:27 +0530170 log<level::ERR>("Failed to get connection",
171 entry("OBJ_NAME=%s", settings_object_name),
172 entry("ERRNO=0x%X", -r));
shgoupfd84fbbf2015-12-17 10:05:51 +0800173 goto finish;
174 }
175
shgoupfd84fbbf2015-12-17 10:05:51 +0800176 /*
177 * Bus, service, object path, interface and method are provided to call
178 * the method.
179 * Signatures and input arguments are provided by the arguments at the
180 * end.
181 */
182 r = sd_bus_call_method(bus,
183 connection, /* service to contact */
184 settings_object_name, /* object path */
185 settings_intf_name, /* interface name */
186 "Get", /* method name */
187 &error, /* object to return error in */
188 &m, /* return message on success */
189 "ss", /* input signature */
190 host_intf_name, /* first argument */
ratagupta6f6bff2016-04-04 06:20:11 -0500191 name); /* second argument */
shgoupfd84fbbf2015-12-17 10:05:51 +0800192
193 if (r < 0) {
Aditya Saripalli5fb14602017-11-09 14:46:27 +0530194 log<level::ERR>("Failed to issue Get method call",
195 entry("ERRNO=0x%X", r));
shgoupfd84fbbf2015-12-17 10:05:51 +0800196 goto finish;
197 }
198
199 /*
200 * The output should be parsed exactly the same as the output formatting
201 * specified.
202 */
203 r = sd_bus_message_read(m, "v", "s", &temp_buf);
204 if (r < 0) {
Aditya Saripalli5fb14602017-11-09 14:46:27 +0530205 log<level::ERR>("Failed to parse response message",
206 entry("ERRNO=0x%X", -r));
shgoupfd84fbbf2015-12-17 10:05:51 +0800207 goto finish;
208 }
209
Matthew Barth56181052017-01-23 09:36:29 -0600210 *buf = strdup(temp_buf);
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500211 /* *buf = (char*) malloc(strlen(temp_buf));
shgoupfd84fbbf2015-12-17 10:05:51 +0800212 if (*buf) {
213 strcpy(*buf, temp_buf);
214 }
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500215 */
Aditya Saripalli5fb14602017-11-09 14:46:27 +0530216
shgoupfd84fbbf2015-12-17 10:05:51 +0800217
218finish:
219 sd_bus_error_free(&error);
220 sd_bus_message_unref(m);
221 free(connection);
222
223 return r;
224}
225
Ratan Guptadcb10672017-07-10 10:33:50 +0530226//TODO : Can remove the below function as we have
227// new functions which uses sdbusplus.
228//
229// openbmc/openbmc#1489
230
ratagupta6f6bff2016-04-04 06:20:11 -0500231int dbus_set_property(const char * name, const char *value)
shgoupfd84fbbf2015-12-17 10:05:51 +0800232{
233 sd_bus_error error = SD_BUS_ERROR_NULL;
234 sd_bus_message *m = NULL;
235 sd_bus *bus = NULL;
236 char *connection = NULL;
237 int r;
238
Brad Bishop35518682016-07-22 08:35:41 -0400239 // Get the system bus where most system services are provided.
240 bus = ipmid_get_sd_bus_connection();
shgoupfd84fbbf2015-12-17 10:05:51 +0800241
Brad Bishop35518682016-07-22 08:35:41 -0400242 r = mapper_get_service(bus, settings_object_name, &connection);
shgoupfd84fbbf2015-12-17 10:05:51 +0800243 if (r < 0) {
Aditya Saripalli5fb14602017-11-09 14:46:27 +0530244 log<level::ERR>("Failed to get connection",
245 entry("OBJ_NAME=%s", settings_object_name),
246 entry("ERRNO=0x%X", -r));
shgoupfd84fbbf2015-12-17 10:05:51 +0800247 goto finish;
248 }
249
shgoupfd84fbbf2015-12-17 10:05:51 +0800250 /*
251 * Bus, service, object path, interface and method are provided to call
252 * the method.
253 * Signatures and input arguments are provided by the arguments at the
254 * end.
255 */
256 r = sd_bus_call_method(bus,
257 connection, /* service to contact */
258 settings_object_name, /* object path */
259 settings_intf_name, /* interface name */
260 "Set", /* method name */
261 &error, /* object to return error in */
262 &m, /* return message on success */
263 "ssv", /* input signature */
264 host_intf_name, /* first argument */
ratagupta6f6bff2016-04-04 06:20:11 -0500265 name, /* second argument */
shgoupfd84fbbf2015-12-17 10:05:51 +0800266 "s", /* third argument */
ratagupta6f6bff2016-04-04 06:20:11 -0500267 value); /* fourth argument */
shgoupfd84fbbf2015-12-17 10:05:51 +0800268
269 if (r < 0) {
Aditya Saripalli5fb14602017-11-09 14:46:27 +0530270 log<level::ERR>("Failed to issue Set method call",
271 entry("ERRNO=0x%X", r));
shgoupfd84fbbf2015-12-17 10:05:51 +0800272 goto finish;
273 }
274
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500275 finish:
shgoupfd84fbbf2015-12-17 10:05:51 +0800276 sd_bus_error_free(&error);
277 sd_bus_message_unref(m);
278 free(connection);
279
280 return r;
281}
282
Adriana Kobylak40814c62015-10-27 15:58:44 -0500283struct get_sys_boot_options_t {
284 uint8_t parameter;
285 uint8_t set;
286 uint8_t block;
287} __attribute__ ((packed));
288
shgoupfd84fbbf2015-12-17 10:05:51 +0800289struct get_sys_boot_options_response_t {
290 uint8_t version;
291 uint8_t parm;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500292 uint8_t data[SIZE_BOOT_OPTION];
shgoupfd84fbbf2015-12-17 10:05:51 +0800293} __attribute__ ((packed));
294
295struct set_sys_boot_options_t {
296 uint8_t parameter;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500297 uint8_t data[SIZE_BOOT_OPTION];
shgoupfd84fbbf2015-12-17 10:05:51 +0800298} __attribute__ ((packed));
299
Ratan Guptafd28dd72016-08-01 04:58:01 -0500300
Ratan Guptadcb10672017-07-10 10:33:50 +0530301int getHostNetworkData(get_sys_boot_options_response_t* respptr)
Ratan Guptafd28dd72016-08-01 04:58:01 -0500302{
Ratan Guptadcb10672017-07-10 10:33:50 +0530303 ipmi::PropertyMap properties;
304 int rc = 0;
Ratan Gupta8c31d232017-08-13 05:49:43 +0530305 uint8_t addrSize = ipmi::network::IPV4_ADDRESS_SIZE_BYTE;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500306
Ratan Guptadcb10672017-07-10 10:33:50 +0530307 try
308 {
309 //TODO There may be cases where an interface is implemented by multiple
310 // objects,to handle such cases we are interested on that object
311 // which are on interested busname.
312 // Currenlty mapper doesn't give the readable busname(gives busid)
313 // so we can't match with bus name so giving some object specific info
314 // as SETTINGS_MATCH.
315 // Later SETTINGS_MATCH will be replaced with busname.
Ratan Guptafd28dd72016-08-01 04:58:01 -0500316
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530317 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
Ratan Guptadcb10672017-07-10 10:33:50 +0530318
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530319 auto ipObjectInfo = ipmi::getDbusObject(bus, IP_INTERFACE,
320 SETTINGS_ROOT, SETTINGS_MATCH);
321
322 auto macObjectInfo = ipmi::getDbusObject(bus, MAC_INTERFACE,
323 SETTINGS_ROOT, SETTINGS_MATCH);
324
325 properties = ipmi::getAllDbusProperties(bus, ipObjectInfo.second,
326 ipObjectInfo.first, IP_INTERFACE);
Ratan Guptacc8feb42017-07-25 21:52:10 +0530327 auto variant =
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530328 ipmi::getDbusProperty(bus, macObjectInfo.second,
329 macObjectInfo.first,
Ratan Guptacc8feb42017-07-25 21:52:10 +0530330 MAC_INTERFACE, "MACAddress");
Ratan Guptadcb10672017-07-10 10:33:50 +0530331
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530332 auto ipAddress = properties["Address"].get<std::string>();
Ratan Guptad70f4532017-08-04 02:07:31 +0530333
334 auto gateway = properties["Gateway"].get<std::string>();
335
336 auto prefix = properties["PrefixLength"].get<uint8_t>();
337
338 uint8_t isStatic = (properties["Origin"].get<std::string>() ==
339 "xyz.openbmc_project.Network.IP.AddressOrigin.Static")
340 ? 1 : 0;
341
Ratan Guptacc8feb42017-07-25 21:52:10 +0530342 auto MACAddress = variant.get<std::string>();
343
Ratan Guptad70f4532017-08-04 02:07:31 +0530344 // it is expected here that we should get the valid data
345 // but we may also get the default values.
346 // Validation of the data is done by settings.
347 //
348 // if mac address is default mac address then
349 // don't send blank override.
Ratan Gupta8c31d232017-08-13 05:49:43 +0530350 if ((MACAddress == ipmi::network::DEFAULT_MAC_ADDRESS))
Ratan Guptad70f4532017-08-04 02:07:31 +0530351 {
352 memset(respptr->data, 0, SIZE_BOOT_OPTION);
353 rc = -1;
354 return rc;
355 }
356 // if addr is static then ipaddress,gateway,prefix
357 // should not be default one,don't send blank override.
358 if (isStatic)
359 {
Ratan Gupta8c31d232017-08-13 05:49:43 +0530360 if((ipAddress == ipmi::network::DEFAULT_ADDRESS) ||
361 (gateway == ipmi::network::DEFAULT_ADDRESS) ||
Ratan Guptad70f4532017-08-04 02:07:31 +0530362 (!prefix))
363 {
364 memset(respptr->data, 0, SIZE_BOOT_OPTION);
365 rc = -1;
366 return rc;
367 }
368 }
369
Ratan Gupta8c31d232017-08-13 05:49:43 +0530370 sscanf(MACAddress.c_str(), ipmi::network::MAC_ADDRESS_FORMAT,
Ratan Guptadcb10672017-07-10 10:33:50 +0530371 (respptr->data + MAC_OFFSET),
372 (respptr->data + MAC_OFFSET + 1),
373 (respptr->data + MAC_OFFSET + 2),
374 (respptr->data + MAC_OFFSET + 3),
375 (respptr->data + MAC_OFFSET + 4),
376 (respptr->data + MAC_OFFSET + 5));
377
Ratan Guptadcb10672017-07-10 10:33:50 +0530378 respptr->data[MAC_OFFSET + 6] = 0x00;
379
Ratan Guptad70f4532017-08-04 02:07:31 +0530380 memcpy(respptr->data + ADDRTYPE_OFFSET, &isStatic,
381 sizeof(isStatic));
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530382
383 uint8_t addressFamily = (properties["Type"].get<std::string>() ==
384 "xyz.openbmc_project.Network.IP.Protocol.IPv4") ?
385 AF_INET : AF_INET6;
386
Ratan Gupta8c31d232017-08-13 05:49:43 +0530387 addrSize = (addressFamily == AF_INET) ?
388 ipmi::network::IPV4_ADDRESS_SIZE_BYTE :
389 ipmi::network::IPV6_ADDRESS_SIZE_BYTE;
Ratan Guptadcb10672017-07-10 10:33:50 +0530390
391 // ipaddress and gateway would be in IPv4 format
Ratan Guptad70f4532017-08-04 02:07:31 +0530392 inet_pton(addressFamily, ipAddress.c_str(),
393 (respptr->data + IPADDR_OFFSET));
Ratan Guptadcb10672017-07-10 10:33:50 +0530394
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530395 uint8_t prefixOffset = IPADDR_OFFSET + addrSize;
396
397 memcpy(respptr->data + prefixOffset, &prefix, sizeof(prefix));
398
399 uint8_t gatewayOffset = prefixOffset + sizeof(decltype(prefix));
400
Ratan Guptad70f4532017-08-04 02:07:31 +0530401 inet_pton(addressFamily, gateway.c_str(),
402 (respptr->data + gatewayOffset));
Ratan Guptadcb10672017-07-10 10:33:50 +0530403
404 }
405 catch (InternalFailure& e)
406 {
407 commit<InternalFailure>();
408 memset(respptr->data, 0, SIZE_BOOT_OPTION);
409 rc = -1;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500410 return rc;
411 }
412
Ratan Guptadcb10672017-07-10 10:33:50 +0530413 //PetiBoot-Specific
Gunnar Mills8991dd62017-10-25 17:11:29 -0500414 //If success then copy the first 9 bytes to the data
Ratan Guptadcb10672017-07-10 10:33:50 +0530415 memcpy(respptr->data, net_conf_initial_bytes,
416 sizeof(net_conf_initial_bytes));
Ratan Guptafd28dd72016-08-01 04:58:01 -0500417
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530418 memcpy(respptr->data + ADDR_SIZE_OFFSET, &addrSize, sizeof(addrSize));
419
Ratan Guptafd28dd72016-08-01 04:58:01 -0500420#ifdef _IPMI_DEBUG_
Ratan Guptadcb10672017-07-10 10:33:50 +0530421 printf("\n===Printing the IPMI Formatted Data========\n");
Ratan Guptafd28dd72016-08-01 04:58:01 -0500422
Ratan Guptadcb10672017-07-10 10:33:50 +0530423 for (uint8_t pos = 0; pos < index; pos++)
424 {
425 printf("%02x ", respptr->data[pos]);
426 }
Ratan Guptafd28dd72016-08-01 04:58:01 -0500427#endif
428
Ratan Guptafd28dd72016-08-01 04:58:01 -0500429 return rc;
430}
431
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530432/** @brief convert IPv4 and IPv6 addresses from binary to text form.
433 * @param[in] family - IPv4/Ipv6
434 * @param[in] data - req data pointer.
435 * @param[in] offset - offset in the data.
436 * @param[in] addrSize - size of the data which needs to be read from offset.
437 * @returns address in text form.
438 */
439
440std::string getAddrStr(uint8_t family, uint8_t* data,
441 uint8_t offset, uint8_t addrSize)
442{
443 char ipAddr[INET6_ADDRSTRLEN] = {};
444
445 switch(family)
446 {
447 case AF_INET:
448 {
449 struct sockaddr_in addr4 {};
450 memcpy(&addr4.sin_addr.s_addr, &data[offset], addrSize);
451
452 inet_ntop(AF_INET, &addr4.sin_addr,
453 ipAddr, INET_ADDRSTRLEN);
454
455 break;
456 }
457 case AF_INET6:
458 {
459 struct sockaddr_in6 addr6 {};
460 memcpy(&addr6.sin6_addr.s6_addr, &data[offset], addrSize);
461
462 inet_ntop(AF_INET6, &addr6.sin6_addr,
463 ipAddr, INET6_ADDRSTRLEN);
464
465 break;
466 }
467 default:
468 {
469 return {};
470 }
471 }
472
473 return ipAddr;
474}
475
Ratan Guptadcb10672017-07-10 10:33:50 +0530476int setHostNetworkData(set_sys_boot_options_t* reqptr)
Ratan Guptafd28dd72016-08-01 04:58:01 -0500477{
Ratan Guptadcb10672017-07-10 10:33:50 +0530478 using namespace std::string_literals;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500479 std::string host_network_config;
Ratan Guptad70f4532017-08-04 02:07:31 +0530480 char mac[] {"00:00:00:00:00:00"};
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530481 std::string ipAddress, gateway;
482 char addrOrigin {0};
483 uint8_t addrSize {0};
Ratan Guptadcb10672017-07-10 10:33:50 +0530484 std::string addressOrigin =
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530485 "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP";
486 std::string addressType =
487 "xyz.openbmc_project.Network.IP.Protocol.IPv4";
Ratan Guptadcb10672017-07-10 10:33:50 +0530488 uint8_t prefix {0};
489 uint32_t zeroCookie = 0;
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530490 uint8_t family = AF_INET;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500491
492 //cookie starts from second byte
493 // version starts from sixth byte
494
Ratan Guptadcb10672017-07-10 10:33:50 +0530495 try
Ratan Guptafd28dd72016-08-01 04:58:01 -0500496 {
Ratan Guptadcb10672017-07-10 10:33:50 +0530497 do
498 {
499 // cookie == 0x21 0x70 0x62 0x21
500 if (memcmp(&(reqptr->data[COOKIE_OFFSET]),
501 (net_conf_initial_bytes + COOKIE_OFFSET),
502 SIZE_COOKIE) != 0)
503 {
504 //cookie == 0
505 if (memcmp(&(reqptr->data[COOKIE_OFFSET]),
506 &zeroCookie,
507 SIZE_COOKIE) == 0)
508 {
509 // need to zero out the network settings.
510 break;
511 }
512
513 log<level::ERR>("Invalid Cookie");
514 elog<InternalFailure>();
515 }
516
517 // vesion == 0x00 0x01
518 if (memcmp(&(reqptr->data[VERSION_OFFSET]),
519 (net_conf_initial_bytes + VERSION_OFFSET),
520 SIZE_VERSION) != 0)
521 {
522
523 log<level::ERR>("Invalid Version");
524 elog<InternalFailure>();
525 }
526
Ratan Gupta8c31d232017-08-13 05:49:43 +0530527 snprintf(mac, SIZE_MAC, ipmi::network::MAC_ADDRESS_FORMAT,
Ratan Guptadcb10672017-07-10 10:33:50 +0530528 reqptr->data[MAC_OFFSET],
529 reqptr->data[MAC_OFFSET + 1],
530 reqptr->data[MAC_OFFSET + 2],
531 reqptr->data[MAC_OFFSET + 3],
532 reqptr->data[MAC_OFFSET + 4],
533 reqptr->data[MAC_OFFSET + 5]);
534
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530535 memcpy(&addrOrigin, &(reqptr->data[ADDRTYPE_OFFSET]),
536 sizeof(decltype(addrOrigin)));
Ratan Guptadcb10672017-07-10 10:33:50 +0530537
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530538 if (addrOrigin)
Ratan Guptadcb10672017-07-10 10:33:50 +0530539 {
540 addressOrigin =
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530541 "xyz.openbmc_project.Network.IP.AddressOrigin.Static";
Ratan Guptadcb10672017-07-10 10:33:50 +0530542 }
543
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530544 // Get the address size
545 memcpy(&addrSize ,&reqptr->data[ADDR_SIZE_OFFSET], sizeof(addrSize));
Ratan Guptadcb10672017-07-10 10:33:50 +0530546
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530547 uint8_t prefixOffset = IPADDR_OFFSET + addrSize;
Ratan Guptadcb10672017-07-10 10:33:50 +0530548
Ratan Guptad70f4532017-08-04 02:07:31 +0530549 memcpy(&prefix, &(reqptr->data[prefixOffset]),
550 sizeof(decltype(prefix)));
Ratan Guptadcb10672017-07-10 10:33:50 +0530551
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530552 uint8_t gatewayOffset = prefixOffset + sizeof(decltype(prefix));
553
Ratan Gupta8c31d232017-08-13 05:49:43 +0530554 if (addrSize != ipmi::network::IPV4_ADDRESS_SIZE_BYTE)
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530555 {
556 addressType = "xyz.openbmc_project.Network.IP.Protocol.IPv6";
557 family = AF_INET6;
558 }
559
560 ipAddress = getAddrStr(family, reqptr->data, IPADDR_OFFSET, addrSize);
Ratan Guptad70f4532017-08-04 02:07:31 +0530561
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530562 gateway = getAddrStr(family, reqptr->data, gatewayOffset, addrSize);
563
Ratan Guptadcb10672017-07-10 10:33:50 +0530564 } while(0);
565
Ratan Guptafd28dd72016-08-01 04:58:01 -0500566 //Cookie == 0 or it is a valid cookie
Ratan Guptadcb10672017-07-10 10:33:50 +0530567 host_network_config += "ipaddress="s + ipAddress +
568 ",prefix="s + std::to_string(prefix) + ",gateway="s + gateway +
569 ",mac="s + mac + ",addressOrigin="s + addressOrigin;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500570
Ratan Guptafd28dd72016-08-01 04:58:01 -0500571
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530572 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
573
574 auto ipObjectInfo = ipmi::getDbusObject(bus, IP_INTERFACE,
575 SETTINGS_ROOT, SETTINGS_MATCH);
576 auto macObjectInfo = ipmi::getDbusObject(bus, MAC_INTERFACE,
577 SETTINGS_ROOT, SETTINGS_MATCH);
Ratan Guptadcb10672017-07-10 10:33:50 +0530578 // set the dbus property
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530579 ipmi::setDbusProperty(bus, ipObjectInfo.second, ipObjectInfo.first,
Ratan Guptadcb10672017-07-10 10:33:50 +0530580 IP_INTERFACE, "Address", std::string(ipAddress));
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530581 ipmi::setDbusProperty(bus, ipObjectInfo.second, ipObjectInfo.first,
Ratan Guptadcb10672017-07-10 10:33:50 +0530582 IP_INTERFACE, "PrefixLength", prefix);
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530583 ipmi::setDbusProperty(bus, ipObjectInfo.second, ipObjectInfo.first,
Ratan Guptadcb10672017-07-10 10:33:50 +0530584 IP_INTERFACE, "Origin", addressOrigin);
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530585 ipmi::setDbusProperty(bus, ipObjectInfo.second, ipObjectInfo.first,
Ratan Guptadcb10672017-07-10 10:33:50 +0530586 IP_INTERFACE, "Gateway", std::string(gateway));
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530587 ipmi::setDbusProperty(bus, ipObjectInfo.second, ipObjectInfo.first,
Ratan Guptadcb10672017-07-10 10:33:50 +0530588 IP_INTERFACE, "Type",
589 std::string("xyz.openbmc_project.Network.IP.Protocol.IPv4"));
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530590 ipmi::setDbusProperty(bus, macObjectInfo.second, macObjectInfo.first,
Ratan Guptadcb10672017-07-10 10:33:50 +0530591 MAC_INTERFACE,"MACAddress", std::string(mac));
Ratan Guptafd28dd72016-08-01 04:58:01 -0500592
Ratan Guptad70f4532017-08-04 02:07:31 +0530593 log<level::DEBUG>("Network configuration changed",
594 entry("NETWORKCONFIG=%s", host_network_config.c_str()));
595
Ratan Guptafd28dd72016-08-01 04:58:01 -0500596 }
Ratan Guptadcb10672017-07-10 10:33:50 +0530597 catch (InternalFailure& e)
598 {
599 commit<InternalFailure>();
600 return -1;
601 }
602
603 return 0;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500604}
605
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -0500606uint32_t getPOHCounter()
607{
608 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
609
610 auto chassisStateObj = ipmi::getDbusObject(bus, chassisPOHStateIntf,
611 chassisStateRoot, match);
612
613 auto service = ipmi::getService(bus, chassisPOHStateIntf,
614 chassisStateObj.first);
615
616 auto propValue = ipmi::getDbusProperty(bus, service, chassisStateObj.first,
617 chassisPOHStateIntf,
618 pOHCounterProperty);
619
620 return propValue.get<uint32_t>();
621}
622
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500623ipmi_ret_t ipmi_chassis_wildcard(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
624 ipmi_request_t request,
625 ipmi_response_t response,
626 ipmi_data_len_t data_len,
627 ipmi_context_t context)
Adriana Kobylak40814c62015-10-27 15:58:44 -0500628{
Adriana Kobylak40814c62015-10-27 15:58:44 -0500629 // Status code.
Nan Li70aa8d92016-08-29 00:11:10 +0800630 ipmi_ret_t rc = IPMI_CC_INVALID;
Adriana Kobylak40814c62015-10-27 15:58:44 -0500631 *data_len = 0;
632 return rc;
633}
634
Nan Li8d15fb42016-08-16 22:29:40 +0800635ipmi_ret_t ipmi_get_chassis_cap(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500636 ipmi_request_t request, ipmi_response_t response,
637 ipmi_data_len_t data_len, ipmi_context_t context)
Nan Li8d15fb42016-08-16 22:29:40 +0800638{
639 // sd_bus error
640 ipmi_ret_t rc = IPMI_CC_OK;
641
642 ipmi_chassis_cap_t chassis_cap{};
643
644 *data_len = sizeof(ipmi_chassis_cap_t);
645
646 // TODO: need future work. Get those flag from MRW.
647
648 // capabilities flags
649 // [7..4] - reserved
650 // [3] – 1b = provides power interlock (IPM 1.5)
651 // [2] – 1b = provides Diagnostic Interrupt (FP NMI)
652 // [1] – 1b = provides “Front Panel Lockout” (indicates that the chassis has capabilities
653 // to lock out external power control and reset button or front panel interfaces
654 // and/or detect tampering with those interfaces).
655 // [0] -1b = Chassis provides intrusion (physical security) sensor.
656 // set to default value 0x0.
657 chassis_cap.cap_flags = 0x0;
658
659 // Since we do not have a separate SDR Device/SEL Device/ FRU repository.
660 // The 20h was given as those 5 device addresses.
661 // Chassis FRU info Device Address
662 chassis_cap.fru_info_dev_addr = 0x20;
663
664 // Chassis SDR Device Address
665 chassis_cap.sdr_dev_addr = 0x20;
666
667 // Chassis SEL Device Address
668 chassis_cap.sel_dev_addr = 0x20;
669
670 // Chassis System Management Device Address
671 chassis_cap.system_management_dev_addr = 0x20;
672
673 // Chassis Bridge Device Address.
674 chassis_cap.bridge_dev_addr = 0x20;
675
676 memcpy(response, &chassis_cap, *data_len);
677
678 return rc;
679}
680
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530681//------------------------------------------
682// Calls into Host State Manager Dbus object
683//------------------------------------------
684int initiate_state_transition(State::Host::Transition transition)
vishwa36993272015-11-20 12:43:49 -0600685{
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500686 // OpenBMC Host State Manager dbus framework
687 constexpr auto HOST_STATE_MANAGER_ROOT = "/xyz/openbmc_project/state/host0";
688 constexpr auto HOST_STATE_MANAGER_IFACE = "xyz.openbmc_project.State.Host";
689 constexpr auto DBUS_PROPERTY_IFACE = "org.freedesktop.DBus.Properties";
690 constexpr auto PROPERTY = "RequestedHostTransition";
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530691
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500692 // sd_bus error
693 int rc = 0;
694 char *busname = NULL;
vishwa36993272015-11-20 12:43:49 -0600695
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500696 // SD Bus error report mechanism.
697 sd_bus_error bus_error = SD_BUS_ERROR_NULL;
vishwa36993272015-11-20 12:43:49 -0600698
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500699 // Gets a hook onto either a SYSTEM or SESSION bus
700 sd_bus *bus_type = ipmid_get_sd_bus_connection();
701 rc = mapper_get_service(bus_type, HOST_STATE_MANAGER_ROOT, &busname);
702 if (rc < 0)
703 {
704 log<level::ERR>("Failed to get bus name",
Aditya Saripalli5fb14602017-11-09 14:46:27 +0530705 entry("ERRNO=0x%X, OBJPATH=%s",
706 -rc, HOST_STATE_MANAGER_ROOT));
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500707 return rc;
708 }
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530709
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500710 // Convert to string equivalent of the passed in transition enum.
711 auto request = State::convertForMessage(transition);
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530712
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500713 rc = sd_bus_call_method(bus_type, // On the system bus
714 busname, // Service to contact
715 HOST_STATE_MANAGER_ROOT, // Object path
716 DBUS_PROPERTY_IFACE, // Interface name
717 "Set", // Method to be called
718 &bus_error, // object to return error
719 nullptr, // Response buffer if any
720 "ssv", // Takes 3 arguments
721 HOST_STATE_MANAGER_IFACE,
722 PROPERTY,
723 "s", request.c_str());
724 if(rc < 0)
725 {
726 log<level::ERR>("Failed to initiate transition",
Aditya Saripalli5fb14602017-11-09 14:46:27 +0530727 entry("ERRNO=0x%X, REQUEST=%s", -rc, request.c_str()));
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500728 }
729 else
730 {
731 log<level::INFO>("Transition request initiated successfully");
732 }
vishwa36993272015-11-20 12:43:49 -0600733
734 sd_bus_error_free(&bus_error);
Sergey Solomineb9b8142016-08-23 09:07:28 -0500735 free(busname);
vishwa36993272015-11-20 12:43:49 -0600736
Sergey Solomineb9b8142016-08-23 09:07:28 -0500737 return rc;
vishwa36993272015-11-20 12:43:49 -0600738}
739
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500740namespace power_policy
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500741{
Nan Lifdd8ec52016-08-28 03:57:40 +0800742
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500743using namespace sdbusplus::xyz::openbmc_project::Control::Power::server;
744using IpmiValue = uint8_t;
745using DbusValue = RestorePolicy::Policy;
Nan Lifdd8ec52016-08-28 03:57:40 +0800746
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500747std::map<DbusValue, IpmiValue> dbusToIpmi =
748{
749 {RestorePolicy::Policy::AlwaysOff, 0x00},
750 {RestorePolicy::Policy::Restore, 0x01},
751 {RestorePolicy::Policy::AlwaysOn, 0x02}
752};
Nan Lifdd8ec52016-08-28 03:57:40 +0800753
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500754} // namespace power_policy
Nan Lifdd8ec52016-08-28 03:57:40 +0800755
756//----------------------------------------------------------------------
757// Get Chassis Status commands
758//----------------------------------------------------------------------
759ipmi_ret_t ipmi_get_chassis_status(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500760 ipmi_request_t request,
761 ipmi_response_t response,
762 ipmi_data_len_t data_len,
763 ipmi_context_t context)
Nan Lifdd8ec52016-08-28 03:57:40 +0800764{
765 const char *objname = "/org/openbmc/control/power0";
766 const char *intf = "org.openbmc.control.Power";
767
768 sd_bus *bus = NULL;
769 sd_bus_message *reply = NULL;
770 int r = 0;
771 int pgood = 0;
772 char *busname = NULL;
773 ipmi_ret_t rc = IPMI_CC_OK;
774 ipmi_get_chassis_status_t chassis_status{};
775
Nan Lifdd8ec52016-08-28 03:57:40 +0800776 uint8_t s = 0;
777
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500778 using namespace chassis::internal;
779 using namespace chassis::internal::cache;
780 using namespace power_policy;
781
Deepak Kodihallie6027092017-08-27 08:13:37 -0500782 const auto& powerRestoreSetting = objects.map.at(powerRestoreIntf).front();
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500783 auto method =
784 dbus.new_method_call(
785 objects.service(powerRestoreSetting, powerRestoreIntf).c_str(),
786 powerRestoreSetting.c_str(),
Ratan Guptacc8feb42017-07-25 21:52:10 +0530787 ipmi::PROP_INTF,
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500788 "Get");
789 method.append(powerRestoreIntf, "PowerRestorePolicy");
790 auto resp = dbus.call(method);
791 if (resp.is_method_error())
792 {
793 log<level::ERR>("Error in PowerRestorePolicy Get");
794 report<InternalFailure>();
795 *data_len = 0;
796 return IPMI_CC_UNSPECIFIED_ERROR;
797 }
798 sdbusplus::message::variant<std::string> result;
799 resp.read(result);
800 auto powerRestore =
801 RestorePolicy::convertPolicyFromString(result.get<std::string>());
Nan Lifdd8ec52016-08-28 03:57:40 +0800802
803 *data_len = 4;
804
Tom Joseph63a00512017-08-09 23:39:59 +0530805 bus = ipmid_get_sd_bus_connection();
806
Nan Lifdd8ec52016-08-28 03:57:40 +0800807 r = mapper_get_service(bus, objname, &busname);
808 if (r < 0) {
Aditya Saripalli5fb14602017-11-09 14:46:27 +0530809 log<level::ERR>("Failed to get bus name",
810 entry("ERRNO=0x%X", -r));
Nan Lifdd8ec52016-08-28 03:57:40 +0800811 rc = IPMI_CC_UNSPECIFIED_ERROR;
812 goto finish;
813 }
814
815 r = sd_bus_get_property(bus, busname, objname, intf, "pgood", NULL, &reply, "i");
816 if (r < 0) {
Aditya Saripalli5fb14602017-11-09 14:46:27 +0530817 log<level::ERR>("Failed to call sd_bus_get_property",
818 entry("PROPERTY=%s","pgood"),
819 entry("ERRNO=0x%X", -r),
820 entry("BUS=%s", busname),
821 entry("PATH=%s", objname),
822 entry("INTERFACE=%s", intf));
Nan Lifdd8ec52016-08-28 03:57:40 +0800823 rc = IPMI_CC_UNSPECIFIED_ERROR;
824 goto finish;
825 }
826
827 r = sd_bus_message_read(reply, "i", &pgood);
828 if (r < 0) {
Aditya Saripalli5fb14602017-11-09 14:46:27 +0530829 log<level::ERR>("Failed to read sensor:",
830 entry("ERRNO=0x%X", -r));
Nan Lifdd8ec52016-08-28 03:57:40 +0800831 rc = IPMI_CC_UNSPECIFIED_ERROR;
832 goto finish;
833 }
834
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500835 s = dbusToIpmi.at(powerRestore);
Nan Lifdd8ec52016-08-28 03:57:40 +0800836
837 // Current Power State
838 // [7] reserved
839 // [6..5] power restore policy
840 // 00b = chassis stays powered off after AC/mains returns
841 // 01b = after AC returns, power is restored to the state that was
842 // in effect when AC/mains was lost.
843 // 10b = chassis always powers up after AC/mains returns
844 // 11b = unknow
845 // Set to 00b, by observing the hardware behavior.
846 // Do we need to define a dbus property to identify the restore policy?
847
848 // [4] power control fault
849 // 1b = controller attempted to turn system power on or off, but
850 // system did not enter desired state.
851 // Set to 0b, since We don't support it..
852
853 // [3] power fault
854 // 1b = fault detected in main power subsystem.
855 // set to 0b. for we don't support it.
856
857 // [2] 1b = interlock (chassis is presently shut down because a chassis
858 // panel interlock switch is active). (IPMI 1.5)
859 // set to 0b, for we don't support it.
860
861 // [1] power overload
862 // 1b = system shutdown because of power overload condition.
863 // set to 0b, for we don't support it.
864
865 // [0] power is on
866 // 1b = system power is on
867 // 0b = system power is off(soft-off S4/S5, or mechanical off)
868
869 chassis_status.cur_power_state = ((s & 0x3)<<5) | (pgood & 0x1);
870
871 // Last Power Event
872 // [7..5] – reserved
873 // [4] – 1b = last ‘Power is on’ state was entered via IPMI command
874 // [3] – 1b = last power down caused by power fault
875 // [2] – 1b = last power down caused by a power interlock being activated
876 // [1] – 1b = last power down caused by a Power overload
877 // [0] – 1b = AC failed
878 // set to 0x0, for we don't support these fields.
879
880 chassis_status.last_power_event = 0;
881
882 // Misc. Chassis State
883 // [7] – reserved
884 // [6] – 1b = Chassis Identify command and state info supported (Optional)
885 // 0b = Chassis Identify command support unspecified via this command.
886 // (The Get Command Support command , if implemented, would still
887 // indicate support for the Chassis Identify command)
888 // [5..4] – Chassis Identify State. Mandatory when bit[6] =1b, reserved (return
889 // as 00b) otherwise. Returns the present chassis identify state.
890 // Refer to the Chassis Identify command for more info.
891 // 00b = chassis identify state = Off
892 // 01b = chassis identify state = Temporary(timed) On
893 // 10b = chassis identify state = Indefinite On
894 // 11b = reserved
895 // [3] – 1b = Cooling/fan fault detected
896 // [2] – 1b = Drive Fault
897 // [1] – 1b = Front Panel Lockout active (power off and reset via chassis
898 // push-buttons disabled.)
899 // [0] – 1b = Chassis Intrusion active
900 // set to 0, for we don't support them.
901 chassis_status.misc_power_state = 0;
902
903 // Front Panel Button Capabilities and disable/enable status(Optional)
904 // set to 0, for we don't support them.
905 chassis_status.front_panel_button_cap_status = 0;
906
907 // Pack the actual response
908 memcpy(response, &chassis_status, *data_len);
909
910finish:
911 free(busname);
912 reply = sd_bus_message_unref(reply);
913
914 return rc;
915}
Chris Austen7888c4d2015-12-03 15:26:20 -0600916
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +0530917//-------------------------------------------------------------
918// Send a command to SoftPowerOff application to stop any timer
919//-------------------------------------------------------------
920int stop_soft_off_timer()
921{
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +0530922 constexpr auto iface = "org.freedesktop.DBus.Properties";
923 constexpr auto soft_off_iface = "xyz.openbmc_project.Ipmi.Internal."
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500924 "SoftPowerOff";
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +0530925
926 constexpr auto property = "ResponseReceived";
927 constexpr auto value = "xyz.openbmc_project.Ipmi.Internal."
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500928 "SoftPowerOff.HostResponse.HostShutdown";
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +0530929
930 // Get the system bus where most system services are provided.
931 auto bus = ipmid_get_sd_bus_connection();
932
933 // Get the service name
Andrew Geissler2b4e4592017-06-08 11:18:35 -0500934 // TODO openbmc/openbmc#1661 - Mapper refactor
935 //
936 // See openbmc/openbmc#1743 for some details but high level summary is that
937 // for now the code will directly call the soft off interface due to a
938 // race condition with mapper usage
939 //
940 //char *busname = nullptr;
941 //auto r = mapper_get_service(bus, SOFTOFF_OBJPATH, &busname);
942 //if (r < 0)
943 //{
944 // fprintf(stderr, "Failed to get %s bus name: %s\n",
Aditya Saripalli5fb14602017-11-09 14:46:27 +0530945 // SOFTOFF_OBJPATH, -r);
Andrew Geissler2b4e4592017-06-08 11:18:35 -0500946 // return r;
947 //}
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +0530948
949 // No error object or reply expected.
Andrew Geissler2b4e4592017-06-08 11:18:35 -0500950 int rc = sd_bus_call_method(bus, SOFTOFF_BUSNAME, SOFTOFF_OBJPATH, iface,
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500951 "Set", nullptr, nullptr, "ssv",
952 soft_off_iface, property, "s", value);
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +0530953 if (rc < 0)
954 {
Aditya Saripalli5fb14602017-11-09 14:46:27 +0530955 log<level::ERR>("Failed to set property in SoftPowerOff object",
956 entry("ERRNO=0x%X", -rc));
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +0530957 }
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500958
Andrew Geissler2b4e4592017-06-08 11:18:35 -0500959 //TODO openbmc/openbmc#1661 - Mapper refactor
960 //free(busname);
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +0530961 return rc;
962}
963
vishwa36993272015-11-20 12:43:49 -0600964//----------------------------------------------------------------------
Andrew Geisslera6e3a302017-05-31 19:34:00 -0500965// Create file to indicate there is no need for softoff notification to host
966//----------------------------------------------------------------------
967void indicate_no_softoff_needed()
968{
969 fs::path path{HOST_INBAND_REQUEST_DIR};
970 if (!fs::is_directory(path))
971 {
972 fs::create_directory(path);
973 }
974
975 // Add the host instance (default 0 for now) to the file name
976 std::string file{HOST_INBAND_REQUEST_FILE};
977 auto size = std::snprintf(nullptr,0,file.c_str(),0);
978 size++; // null
979 std::unique_ptr<char[]> buf(new char[size]);
980 std::snprintf(buf.get(),size,file.c_str(),0);
981
982 // Append file name to directory and create it
983 path /= buf.get();
984 std::ofstream(path.c_str());
985}
986
987//----------------------------------------------------------------------
vishwa36993272015-11-20 12:43:49 -0600988// Chassis Control commands
989//----------------------------------------------------------------------
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500990ipmi_ret_t ipmi_chassis_control(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
991 ipmi_request_t request,
992 ipmi_response_t response,
993 ipmi_data_len_t data_len,
994 ipmi_context_t context)
vishwa36993272015-11-20 12:43:49 -0600995{
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500996 // Error from power off.
997 int rc = 0;
vishwa36993272015-11-20 12:43:49 -0600998
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500999 // No response for this command.
vishwa36993272015-11-20 12:43:49 -06001000 *data_len = 0;
1001
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001002 // Catch the actual operaton by peeking into request buffer
1003 uint8_t chassis_ctrl_cmd = *(uint8_t *)request;
vishwa36993272015-11-20 12:43:49 -06001004
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001005 switch(chassis_ctrl_cmd)
1006 {
1007 case CMD_POWER_ON:
1008 rc = initiate_state_transition(State::Host::Transition::On);
1009 break;
1010 case CMD_POWER_OFF:
Vishwanatha Subbanna8b26d352017-08-04 18:35:18 +05301011 // This path would be hit in 2 conditions.
1012 // 1: When user asks for power off using ipmi chassis command 0x04
1013 // 2: Host asking for power off post shutting down.
1014
1015 // If it's a host requested power off, then need to nudge Softoff
1016 // application that it needs to stop the watchdog timer if running.
1017 // If it is a user requested power off, then this is not really
1018 // needed. But then we need to differentiate between user and host
1019 // calling this same command
1020
1021 // For now, we are going ahead with trying to nudge the soft off and
1022 // interpret the failure to do so as a non softoff case
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001023 rc = stop_soft_off_timer();
Vishwanatha Subbanna8b26d352017-08-04 18:35:18 +05301024
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001025 // Only request the Off transition if the soft power off
1026 // application is not running
1027 if (rc < 0)
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001028 {
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001029 // First create a file to indicate to the soft off application
Vishwanatha Subbanna8b26d352017-08-04 18:35:18 +05301030 // that it should not run. Not doing this will result in State
1031 // manager doing a default soft power off when asked for power
1032 // off.
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001033 indicate_no_softoff_needed();
1034
1035 // Now request the shutdown
1036 rc = initiate_state_transition(State::Host::Transition::Off);
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001037 }
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001038 else
1039 {
Vishwanatha Subbanna8b26d352017-08-04 18:35:18 +05301040 log<level::INFO>("Soft off is running, so let shutdown target "
1041 "stop the host");
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001042 }
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001043 break;
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +05301044
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001045 case CMD_HARD_RESET:
1046 case CMD_POWER_CYCLE:
1047 // SPEC has a section that says certain implementations can trigger
1048 // PowerOn if power is Off when a command to power cycle is
1049 // requested
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001050
1051 // First create a file to indicate to the soft off application
1052 // that it should not run since this is a direct user initiated
1053 // power reboot request (i.e. a reboot request that is not
1054 // originating via a soft power off SMS request)
1055 indicate_no_softoff_needed();
1056
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001057 rc = initiate_state_transition(State::Host::Transition::Reboot);
1058 break;
Vishwanatha Subbanna8b26d352017-08-04 18:35:18 +05301059
1060 case CMD_SOFT_OFF_VIA_OVER_TEMP:
1061 // Request Host State Manager to do a soft power off
1062 rc = initiate_state_transition(State::Host::Transition::Off);
1063 break;
1064
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001065 default:
1066 {
Aditya Saripalli5fb14602017-11-09 14:46:27 +05301067 log<level::ERR>("Invalid Chassis Control command",
1068 entry("CMD=0x%X", chassis_ctrl_cmd));
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001069 rc = -1;
1070 }
1071 }
vishwa36993272015-11-20 12:43:49 -06001072
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001073 return ( (rc < 0) ? IPMI_CC_INVALID : IPMI_CC_OK);
vishwa36993272015-11-20 12:43:49 -06001074}
1075
Tom Joseph5110c122018-03-23 17:55:40 +05301076ipmi_ret_t ipmi_chassis_identify(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1077 ipmi_request_t request,
1078 ipmi_response_t response,
1079 ipmi_data_len_t data_len,
1080 ipmi_context_t context)
1081{
1082 static std::atomic_size_t currentCallerId(0);
1083 static std::unique_ptr<std::future<void>> future;
1084 static std::condition_variable condition;
1085 static std::mutex timeoutMutex;
1086
1087 if (*data_len > 2)
1088 {
1089 return IPMI_CC_REQ_DATA_LEN_INVALID;
1090 }
1091 uint8_t identifyInterval = *data_len > 0 ?
1092 (static_cast<uint8_t*>(request))[0] :
1093 DEFAULT_IDENTIFY_TIME_OUT;
1094 bool forceIdentify =
1095 *data_len == 2 ? (static_cast<uint8_t*>(request))[1] & 0x01 : false;
1096
1097 currentCallerId++;
1098
1099 // stop any threads currently running
1100 condition.notify_all();
1101
1102 // lookup enclosure_identify group owner(s) in mapper
1103 auto mapperCall = chassis::internal::dbus.new_method_call(
1104 ipmi::MAPPER_BUS_NAME,
1105 ipmi::MAPPER_OBJ,
1106 ipmi::MAPPER_INTF,
1107 "GetObject");
1108
1109 mapperCall.append(identify_led_object_name);
1110 static const std::vector<std::string> interfaces =
1111 {
1112 "xyz.openbmc_project.Led.Group"
1113 };
1114 mapperCall.append(interfaces);
1115 auto mapperReply = chassis::internal::dbus.call(mapperCall);
1116 if (mapperReply.is_method_error())
1117 {
1118 log<level::ERR>("Chassis Identify: Error communicating to mapper.");
1119 return IPMI_CC_RESPONSE_ERROR;
1120 }
1121 std::vector<std::pair<std::string, std::vector<std::string>>> mapperResp;
1122 mapperReply.read(mapperResp);
1123
1124 for (auto& object : mapperResp)
1125 {
1126 std::string& connection = object.first;
1127
1128 if (identifyInterval || forceIdentify)
1129 {
1130 auto ledOn = chassis::internal::dbus.new_method_call(
1131 connection.c_str(),
1132 identify_led_object_name,
1133 "org.freedesktop.DBus.Properties", "Set");
1134 ledOn.append(
1135 "xyz.openbmc_project.Led.Group", "Asserted",
1136 sdbusplus::message::variant<bool>(
1137 true));
1138 auto ledReply = chassis::internal::dbus.call(ledOn);
1139 if (ledReply.is_method_error())
1140 {
1141 log<level::ERR>("Chassis Identify: Error Setting State On\n");
1142 return IPMI_CC_RESPONSE_ERROR;
1143 }
1144 if (forceIdentify)
1145 {
1146 return IPMI_CC_OK;
1147 }
1148 }
1149
1150 size_t threadCallerId = currentCallerId;
1151 future = std::make_unique<std::future<void>>(
1152 std::async(std::launch::async,
1153 [connection,
1154 identifyInterval,
1155 threadCallerId]
1156 {
1157 std::unique_lock<std::mutex> lock(timeoutMutex);
1158 if (condition.wait_for(lock,
1159 std::chrono::seconds(identifyInterval),
1160 [&threadCallerId]{return currentCallerId != threadCallerId;}))
1161 {
1162 return; // another thread started.
1163 }
1164 auto ledOff = chassis::internal::dbus.new_method_call(
1165 connection.c_str(),
1166 identify_led_object_name,
1167 "org.freedesktop.DBus.Properties", "Set");
1168 ledOff.append("xyz.openbmc_project.Led.Group", "Asserted",
1169 sdbusplus::message::variant<bool>(
1170 false));
1171 auto ledReply = chassis::internal::dbus.call(ledOff);
1172 if (ledReply.is_method_error())
1173 {
1174 log<level::ERR>("Chassis Identify: Error Setting State Off\n");
1175 }
1176 }));
1177 }
1178 return IPMI_CC_OK;
1179}
1180
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001181namespace boot_options
1182{
1183
1184using namespace sdbusplus::xyz::openbmc_project::Control::Boot::server;
1185using IpmiValue = uint8_t;
1186constexpr auto ipmiDefault = 0;
1187
1188std::map<IpmiValue, Source::Sources> sourceIpmiToDbus =
1189{
1190 {0x01, Source::Sources::Network},
1191 {0x02, Source::Sources::Disk},
1192 {0x05, Source::Sources::ExternalMedia},
1193 {ipmiDefault, Source::Sources::Default}
shgoupfd84fbbf2015-12-17 10:05:51 +08001194};
1195
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001196std::map<IpmiValue, Mode::Modes> modeIpmiToDbus =
1197{
1198 {0x03, Mode::Modes::Safe},
1199 {0x06, Mode::Modes::Setup},
1200 {ipmiDefault, Mode::Modes::Regular}
shgoupfd84fbbf2015-12-17 10:05:51 +08001201};
1202
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001203std::map<Source::Sources, IpmiValue> sourceDbusToIpmi =
1204{
1205 {Source::Sources::Network, 0x01},
1206 {Source::Sources::Disk, 0x02},
1207 {Source::Sources::ExternalMedia, 0x05},
1208 {Source::Sources::Default, ipmiDefault}
1209};
shgoupfd84fbbf2015-12-17 10:05:51 +08001210
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001211std::map<Mode::Modes, IpmiValue> modeDbusToIpmi =
1212{
1213 {Mode::Modes::Safe, 0x03},
1214 {Mode::Modes::Setup, 0x06},
1215 {Mode::Modes::Regular, ipmiDefault}
1216};
shgoupfd84fbbf2015-12-17 10:05:51 +08001217
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001218} // namespace boot_options
shgoupfd84fbbf2015-12-17 10:05:51 +08001219
Marri Devender Rao81719702018-05-07 00:53:48 -05001220
1221/** @brief Set the property value for boot source
1222 * @param[in] source - boot source value
1223 * @return On failure return IPMI error.
1224 */
1225static ipmi_ret_t setBootSource(const Source::Sources& source)
1226{
1227 using namespace chassis::internal;
1228 using namespace chassis::internal::cache;
1229 sdbusplus::message::variant<std::string> property =
1230 convertForMessage(source);
1231 auto bootSetting = settings::boot::setting(objects, bootSourceIntf);
1232 const auto& bootSourceSetting = std::get<settings::Path>(bootSetting);
1233 auto method =
1234 dbus.new_method_call(
1235 objects.service(bootSourceSetting, bootSourceIntf).c_str(),
1236 bootSourceSetting.c_str(), ipmi::PROP_INTF, "Set");
1237 method.append(bootSourceIntf, "BootSource", property);
1238 auto reply = dbus.call(method);
1239 if (reply.is_method_error())
1240 {
1241 log<level::ERR>("Error in BootSource Set");
1242 report<InternalFailure>();
1243 return IPMI_CC_UNSPECIFIED_ERROR;
1244 }
1245 return IPMI_CC_OK;
1246}
1247
1248 /** @brief Set the property value for boot mode
1249 * @param[in] mode - boot mode value
1250 * @return On failure return IPMI error.
1251 */
1252static ipmi_ret_t setBootMode(const Mode::Modes& mode)
1253{
1254 using namespace chassis::internal;
1255 using namespace chassis::internal::cache;
1256 sdbusplus::message::variant<std::string> property =
1257 convertForMessage(mode);
1258 auto bootSetting = settings::boot::setting(objects, bootModeIntf);
1259 const auto& bootModeSetting = std::get<settings::Path>(bootSetting);
1260 auto method =
1261 dbus.new_method_call(
1262 objects.service(bootModeSetting, bootModeIntf).c_str(),
1263 bootModeSetting.c_str(), ipmi::PROP_INTF, "Set");
1264 method.append(bootModeIntf, "BootMode", property);
1265 auto reply = dbus.call(method);
1266 if (reply.is_method_error())
1267 {
1268 log<level::ERR>("Error in BootMode Set");
1269 report<InternalFailure>();
1270 return IPMI_CC_UNSPECIFIED_ERROR;
1271 }
1272 return IPMI_CC_OK;
1273}
1274
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001275ipmi_ret_t ipmi_chassis_get_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1276 ipmi_request_t request,
1277 ipmi_response_t response,
1278 ipmi_data_len_t data_len,
1279 ipmi_context_t context)
Adriana Kobylak40814c62015-10-27 15:58:44 -05001280{
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001281 using namespace boot_options;
shgoupfd84fbbf2015-12-17 10:05:51 +08001282 ipmi_ret_t rc = IPMI_CC_PARM_NOT_SUPPORTED;
1283 char *p = NULL;
1284 get_sys_boot_options_response_t *resp = (get_sys_boot_options_response_t *) response;
1285 get_sys_boot_options_t *reqptr = (get_sys_boot_options_t*) request;
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001286 IpmiValue bootOption = ipmiDefault;
Adriana Kobylak40814c62015-10-27 15:58:44 -05001287
shgoupfd84fbbf2015-12-17 10:05:51 +08001288 memset(resp,0,sizeof(*resp));
1289 resp->version = SET_PARM_VERSION;
1290 resp->parm = 5;
ratagupta6f6bff2016-04-04 06:20:11 -05001291 resp->data[0] = SET_PARM_BOOT_FLAGS_VALID_ONE_TIME;
Adriana Kobylak40814c62015-10-27 15:58:44 -05001292
Adriana Kobylak40814c62015-10-27 15:58:44 -05001293
shgoupfd84fbbf2015-12-17 10:05:51 +08001294 /*
1295 * Parameter #5 means boot flags. Please refer to 28.13 of ipmi doc.
1296 * This is the only parameter used by petitboot.
1297 */
Ratan Guptafd28dd72016-08-01 04:58:01 -05001298 if ( reqptr->parameter == static_cast<uint8_t>
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001299 ( BootOptionParameter::BOOT_FLAGS )) {
shgoupfd84fbbf2015-12-17 10:05:51 +08001300
Ratan Guptafd28dd72016-08-01 04:58:01 -05001301 *data_len = static_cast<uint8_t>(BootOptionResponseSize::BOOT_FLAGS);
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001302 using namespace chassis::internal;
1303 using namespace chassis::internal::cache;
shgoupfd84fbbf2015-12-17 10:05:51 +08001304
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001305 try
ratagupta6f6bff2016-04-04 06:20:11 -05001306 {
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001307 auto bootSetting = settings::boot::setting(objects, bootSourceIntf);
1308 const auto& bootSourceSetting =
1309 std::get<settings::Path>(bootSetting);
1310 auto oneTimeEnabled =
1311 std::get<settings::boot::OneTimeEnabled>(bootSetting);
1312 auto method =
1313 dbus.new_method_call(
1314 objects.service(bootSourceSetting, bootSourceIntf).c_str(),
1315 bootSourceSetting.c_str(),
1316 ipmi::PROP_INTF,
1317 "Get");
1318 method.append(bootSourceIntf, "BootSource");
1319 auto reply = dbus.call(method);
1320 if (reply.is_method_error())
1321 {
1322 log<level::ERR>("Error in BootSource Get");
1323 report<InternalFailure>();
1324 *data_len = 0;
1325 return IPMI_CC_UNSPECIFIED_ERROR;
1326 }
1327 sdbusplus::message::variant<std::string> result;
1328 reply.read(result);
1329 auto bootSource =
1330 Source::convertSourcesFromString(result.get<std::string>());
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001331
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001332 bootSetting = settings::boot::setting(objects, bootModeIntf);
1333 const auto& bootModeSetting = std::get<settings::Path>(bootSetting);
1334 method = dbus.new_method_call(
1335 objects.service(bootModeSetting, bootModeIntf).
1336 c_str(),
1337 bootModeSetting.c_str(),
1338 ipmi::PROP_INTF,
1339 "Get");
1340 method.append(bootModeIntf, "BootMode");
1341 reply = dbus.call(method);
1342 if (reply.is_method_error())
1343 {
1344 log<level::ERR>("Error in BootMode Get");
1345 report<InternalFailure>();
1346 *data_len = 0;
1347 return IPMI_CC_UNSPECIFIED_ERROR;
1348 }
1349 reply.read(result);
1350 auto bootMode =
1351 Mode::convertModesFromString(result.get<std::string>());
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001352
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001353 bootOption = sourceDbusToIpmi.at(bootSource);
1354 if ((Mode::Modes::Regular == bootMode) &&
1355 (Source::Sources::Default == bootSource))
1356 {
1357 bootOption = ipmiDefault;
1358 }
1359 else if (Source::Sources::Default == bootSource)
1360 {
1361 bootOption = modeDbusToIpmi.at(bootMode);
1362 }
1363 resp->data[1] = (bootOption << 2);
ratagupta6f6bff2016-04-04 06:20:11 -05001364
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001365 resp->data[0] = oneTimeEnabled ?
1366 SET_PARM_BOOT_FLAGS_VALID_ONE_TIME:
1367 SET_PARM_BOOT_FLAGS_VALID_PERMANENT;
ratagupta6f6bff2016-04-04 06:20:11 -05001368
ratagupta6f6bff2016-04-04 06:20:11 -05001369 rc = IPMI_CC_OK;
ratagupta6f6bff2016-04-04 06:20:11 -05001370 }
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001371 catch (InternalFailure& e)
1372 {
1373 report<InternalFailure>();
1374 *data_len = 0;
1375 return IPMI_CC_UNSPECIFIED_ERROR;
1376 }
Ratan Guptafd28dd72016-08-01 04:58:01 -05001377 } else if ( reqptr->parameter == static_cast<uint8_t>
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001378 ( BootOptionParameter::OPAL_NETWORK_SETTINGS )) {
Ratan Guptafd28dd72016-08-01 04:58:01 -05001379
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001380 *data_len = static_cast<uint8_t>(BootOptionResponseSize::OPAL_NETWORK_SETTINGS);
Ratan Guptafd28dd72016-08-01 04:58:01 -05001381
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001382 resp->parm = static_cast<uint8_t>(BootOptionParameter::OPAL_NETWORK_SETTINGS);
Ratan Guptafd28dd72016-08-01 04:58:01 -05001383
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001384 int ret = getHostNetworkData(resp);
Ratan Guptafd28dd72016-08-01 04:58:01 -05001385
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001386 if (ret < 0) {
Ratan Guptafd28dd72016-08-01 04:58:01 -05001387
Aditya Saripalli5fb14602017-11-09 14:46:27 +05301388 log<level::ERR>(
1389 "getHostNetworkData failed for get_sys_boot_options.");
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001390 rc = IPMI_CC_UNSPECIFIED_ERROR;
Ratan Guptafd28dd72016-08-01 04:58:01 -05001391
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001392 }else
1393 rc = IPMI_CC_OK;
Ratan Guptafd28dd72016-08-01 04:58:01 -05001394 }
1395
1396 else {
Aditya Saripalli5fb14602017-11-09 14:46:27 +05301397 log<level::ERR>("Unsupported parameter", entry(
1398 "PARAM=0x%x", reqptr->parameter));
shgoupfd84fbbf2015-12-17 10:05:51 +08001399 }
1400
1401 if (p)
1402 free(p);
1403
Ratan Guptafd28dd72016-08-01 04:58:01 -05001404 if (rc == IPMI_CC_OK)
1405 {
1406 *data_len += 2;
1407 }
1408
shgoupfd84fbbf2015-12-17 10:05:51 +08001409 return rc;
1410}
1411
1412
1413
1414ipmi_ret_t ipmi_chassis_set_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001415 ipmi_request_t request,
1416 ipmi_response_t response,
1417 ipmi_data_len_t data_len,
1418 ipmi_context_t context)
shgoupfd84fbbf2015-12-17 10:05:51 +08001419{
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001420 using namespace boot_options;
shgoupfd84fbbf2015-12-17 10:05:51 +08001421 ipmi_ret_t rc = IPMI_CC_OK;
shgoupfd84fbbf2015-12-17 10:05:51 +08001422 set_sys_boot_options_t *reqptr = (set_sys_boot_options_t *) request;
1423
Ratan Guptafd28dd72016-08-01 04:58:01 -05001424 printf("IPMI SET_SYS_BOOT_OPTIONS reqptr->parameter =[%d]\n",reqptr->parameter);
1425
shgoupfd84fbbf2015-12-17 10:05:51 +08001426 // This IPMI command does not have any resposne data
1427 *data_len = 0;
1428
1429 /* 000101
1430 * Parameter #5 means boot flags. Please refer to 28.13 of ipmi doc.
1431 * This is the only parameter used by petitboot.
1432 */
Ratan Guptafd28dd72016-08-01 04:58:01 -05001433
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001434 if (reqptr->parameter == (uint8_t)BootOptionParameter::BOOT_FLAGS)
1435 {
1436 IpmiValue bootOption = ((reqptr->data[1] & 0x3C) >> 2);
1437 using namespace chassis::internal;
1438 using namespace chassis::internal::cache;
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001439 auto oneTimeEnabled = false;
1440 constexpr auto enabledIntf = "xyz.openbmc_project.Object.Enable";
Tom Joseph57e8eb72017-09-25 18:05:02 +05301441 constexpr auto oneTimePath =
1442 "/xyz/openbmc_project/control/host0/boot/one_time";
shgoupfd84fbbf2015-12-17 10:05:51 +08001443
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001444 try
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001445 {
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001446 bool permanent =
1447 (reqptr->data[0] & SET_PARM_BOOT_FLAGS_PERMANENT) ==
1448 SET_PARM_BOOT_FLAGS_PERMANENT;
1449
Tom Joseph57e8eb72017-09-25 18:05:02 +05301450 auto bootSetting =
1451 settings::boot::setting(objects, bootSourceIntf);
1452
1453 oneTimeEnabled =
1454 std::get<settings::boot::OneTimeEnabled>(bootSetting);
1455
1456 /*
1457 * Check if the current boot setting is onetime or permanent, if the
1458 * request in the command is otherwise, then set the "Enabled"
1459 * property in one_time object path to 'True' to indicate onetime
1460 * and 'False' to indicate permanent.
1461 *
1462 * Once the onetime/permanent setting is applied, then the bootMode
1463 * and bootSource is updated for the corresponding object.
1464 */
1465 if ((permanent && oneTimeEnabled) ||
1466 (!permanent && !oneTimeEnabled))
1467 {
1468 auto service = ipmi::getService(dbus, enabledIntf, oneTimePath);
1469
1470 ipmi::setDbusProperty(dbus,
1471 service,
1472 oneTimePath,
1473 enabledIntf,
1474 "Enabled",
1475 !permanent);
1476 }
1477
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001478 auto modeItr = modeIpmiToDbus.find(bootOption);
1479 auto sourceItr = sourceIpmiToDbus.find(bootOption);
1480 if (sourceIpmiToDbus.end() != sourceItr)
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001481 {
Marri Devender Rao81719702018-05-07 00:53:48 -05001482 rc = setBootSource(sourceItr->second);
1483 if (rc != IPMI_CC_OK)
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001484 {
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001485 *data_len = 0;
Marri Devender Rao81719702018-05-07 00:53:48 -05001486 return rc;
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001487 }
Marri Devender Rao54fa1302018-05-07 01:06:23 -05001488 // If a set boot device is mapping to a boot source, then reset
1489 // the boot mode D-Bus property to default.
1490 // This way the ipmid code can determine which property is not
1491 // at the default value
1492 if(sourceItr->second != Source::Sources::Default)
1493 {
1494 setBootMode(Mode::Modes::Regular);
1495 }
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001496 }
1497 if (modeIpmiToDbus.end() != modeItr)
1498 {
Marri Devender Rao81719702018-05-07 00:53:48 -05001499 rc = setBootMode(modeItr->second);
1500 if (rc != IPMI_CC_OK)
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001501 {
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001502 *data_len = 0;
Marri Devender Rao81719702018-05-07 00:53:48 -05001503 return rc;
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001504 }
Marri Devender Rao54fa1302018-05-07 01:06:23 -05001505 // If a set boot device is mapping to a boot mode, then reset
1506 // the boot source D-Bus property to default.
1507 // This way the ipmid code can determine which property is not
1508 // at the default value
1509 if(modeItr->second != Mode::Modes::Regular)
1510 {
1511 setBootSource(Source::Sources::Default);
1512 }
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001513 }
1514 }
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001515 catch (InternalFailure& e)
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001516 {
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001517 report<InternalFailure>();
1518 *data_len = 0;
1519 return IPMI_CC_UNSPECIFIED_ERROR;
shgoupfd84fbbf2015-12-17 10:05:51 +08001520 }
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001521 } else if (reqptr->parameter ==
1522 (uint8_t)BootOptionParameter::OPAL_NETWORK_SETTINGS) {
Ratan Guptafd28dd72016-08-01 04:58:01 -05001523
1524 int ret = setHostNetworkData(reqptr);
1525 if (ret < 0) {
Aditya Saripalli5fb14602017-11-09 14:46:27 +05301526 log<level::ERR>(
1527 "setHostNetworkData failed for set_sys_boot_options");
Ratan Guptafd28dd72016-08-01 04:58:01 -05001528 rc = IPMI_CC_UNSPECIFIED_ERROR;
1529 }
Tom Josephf536c902017-09-25 18:08:15 +05301530 } else if (reqptr->parameter ==
1531 static_cast<uint8_t>(BootOptionParameter::BOOT_INFO)) {
1532 // Handle parameter #4 and return command completed normally
1533 // (IPMI_CC_OK). There is no implementation in OpenBMC for this
1534 // parameter. This is added to support the ipmitool command `chassis
1535 // bootdev` which sends set on parameter #4, before setting the boot
1536 // flags.
1537 rc = IPMI_CC_OK;
1538 } else {
Aditya Saripalli5fb14602017-11-09 14:46:27 +05301539 log<level::ERR>("Unsupported parameter", entry(
1540 "PARAM=0x%x", reqptr->parameter));
shgoupfd84fbbf2015-12-17 10:05:51 +08001541 rc = IPMI_CC_PARM_NOT_SUPPORTED;
Adriana Kobylak40814c62015-10-27 15:58:44 -05001542 }
1543
1544 return rc;
1545}
1546
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -05001547ipmi_ret_t ipmiGetPOHCounter(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1548 ipmi_request_t request, ipmi_response_t response,
1549 ipmi_data_len_t data_len, ipmi_context_t context)
1550{
1551 // sd_bus error
1552 ipmi_ret_t rc = IPMI_CC_OK;
1553
1554 auto resptr = reinterpret_cast<GetPOHCountResponse*>(response);
1555
1556 try
1557 {
1558 auto pohCounter = getPOHCounter();
1559 resptr->counterReading[0] = pohCounter;
1560 resptr->counterReading[1] = pohCounter >> 8;
1561 resptr->counterReading[2] = pohCounter >> 16;
1562 resptr->counterReading[3] = pohCounter >> 24;
1563 }
1564 catch (std::exception& e)
1565 {
1566 log<level::ERR>(e.what());
1567 return IPMI_CC_UNSPECIFIED_ERROR;
1568 }
1569
1570 resptr->minPerCount = poh::minutesPerCount;
1571 *data_len = sizeof(GetPOHCountResponse);
1572
1573 return rc;
1574}
1575
Adriana Kobylak40814c62015-10-27 15:58:44 -05001576void register_netfn_chassis_functions()
1577{
Tom05732372016-09-06 17:21:23 +05301578 // <Wildcard Command>
Tom05732372016-09-06 17:21:23 +05301579 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_WILDCARD, NULL, ipmi_chassis_wildcard,
1580 PRIVILEGE_USER);
Adriana Kobylak40814c62015-10-27 15:58:44 -05001581
Tom05732372016-09-06 17:21:23 +05301582 // Get Chassis Capabilities
Tom05732372016-09-06 17:21:23 +05301583 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_GET_CHASSIS_CAP, NULL, ipmi_get_chassis_cap,
1584 PRIVILEGE_USER);
Nan Li8d15fb42016-08-16 22:29:40 +08001585
Tom05732372016-09-06 17:21:23 +05301586 // <Get System Boot Options>
Tom05732372016-09-06 17:21:23 +05301587 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_GET_SYS_BOOT_OPTIONS, NULL,
1588 ipmi_chassis_get_sys_boot_options, PRIVILEGE_OPERATOR);
Adriana Kobylak40814c62015-10-27 15:58:44 -05001589
Tom05732372016-09-06 17:21:23 +05301590 // <Get Chassis Status>
Tom05732372016-09-06 17:21:23 +05301591 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_CHASSIS_STATUS, NULL, ipmi_get_chassis_status,
1592 PRIVILEGE_USER);
Nan Lifdd8ec52016-08-28 03:57:40 +08001593
Tom05732372016-09-06 17:21:23 +05301594 // <Chassis Control>
Tom05732372016-09-06 17:21:23 +05301595 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_CHASSIS_CONTROL, NULL, ipmi_chassis_control,
1596 PRIVILEGE_OPERATOR);
shgoupfd84fbbf2015-12-17 10:05:51 +08001597
Tom Joseph5110c122018-03-23 17:55:40 +05301598 // <Chassis Identify>
Tom Joseph5110c122018-03-23 17:55:40 +05301599 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_CHASSIS_IDENTIFY, NULL,
1600 ipmi_chassis_identify, PRIVILEGE_OPERATOR);
1601
Tom05732372016-09-06 17:21:23 +05301602 // <Set System Boot Options>
Tom05732372016-09-06 17:21:23 +05301603 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_SET_SYS_BOOT_OPTIONS, NULL,
1604 ipmi_chassis_set_sys_boot_options, PRIVILEGE_OPERATOR);
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -05001605 // <Get POH Counter>
1606 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_GET_POH_COUNTER, NULL,
1607 ipmiGetPOHCounter, PRIVILEGE_USER);
vishwa36993272015-11-20 12:43:49 -06001608}