blob: a58eee0aeb890205faab27fc9609a3af719753e1 [file] [log] [blame]
Patrick Venture46470a32018-09-07 19:26:25 -07001#include "config.h"
2
3#include "chassishandler.hpp"
Patrick Venture0b02be92018-08-31 11:55:55 -07004
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05005#include "ipmid.hpp"
6#include "settings.hpp"
Patrick Venture0b02be92018-08-31 11:55:55 -07007#include "types.hpp"
Ratan Guptacc8feb42017-07-25 21:52:10 +05308#include "utils.hpp"
Ratan Guptadcb10672017-07-10 10:33:50 +05309
Patrick Venture0b02be92018-08-31 11:55:55 -070010#include <arpa/inet.h>
11#include <endian.h>
Patrick Venture46470a32018-09-07 19:26:25 -070012#include <host-ipmid/ipmid-api.h>
Patrick Venture0b02be92018-08-31 11:55:55 -070013#include <limits.h>
14#include <mapper.h>
15#include <netinet/in.h>
Patrick Venture0b02be92018-08-31 11:55:55 -070016
Ratan Guptafd28dd72016-08-01 04:58:01 -050017#include <array>
Patrick Venture0b02be92018-08-31 11:55:55 -070018#include <chrono>
Patrick Ventureb51bf9c2018-09-10 15:53:14 -070019#include <cstring>
Andrew Geisslera6e3a302017-05-31 19:34:00 -050020#include <fstream>
Tom Joseph5110c122018-03-23 17:55:40 +053021#include <future>
Patrick Venture3a5071a2018-09-12 13:27:42 -070022#include <map>
23#include <phosphor-logging/elog-errors.hpp>
24#include <phosphor-logging/log.hpp>
25#include <sdbusplus/bus.hpp>
William A. Kennington III4c008022018-10-12 17:18:14 -070026#include <sdbusplus/message/types.hpp>
Patrick Venture3a5071a2018-09-12 13:27:42 -070027#include <sdbusplus/server/object.hpp>
Vernon Mauery1181af72018-10-08 12:05:00 -070028#include <sdbusplus/timer.hpp>
Patrick Venture0b02be92018-08-31 11:55:55 -070029#include <sstream>
Patrick Venture3a5071a2018-09-12 13:27:42 -070030#include <string>
31#include <xyz/openbmc_project/Common/error.hpp>
32#include <xyz/openbmc_project/Control/Boot/Mode/server.hpp>
33#include <xyz/openbmc_project/Control/Boot/Source/server.hpp>
34#include <xyz/openbmc_project/Control/Power/RestorePolicy/server.hpp>
35#include <xyz/openbmc_project/State/Host/server.hpp>
36#include <xyz/openbmc_project/State/PowerOnHours/server.hpp>
37
Vernon Mauery185b9f82018-07-20 10:52:36 -070038#if __has_include(<filesystem>)
39#include <filesystem>
40#elif __has_include(<experimental/filesystem>)
Andrew Geisslera6e3a302017-05-31 19:34:00 -050041#include <experimental/filesystem>
Patrick Venture0b02be92018-08-31 11:55:55 -070042namespace std
43{
44// splice experimental::filesystem into std
45namespace filesystem = std::experimental::filesystem;
46} // namespace std
Vernon Mauery185b9f82018-07-20 10:52:36 -070047#else
Patrick Venture0b02be92018-08-31 11:55:55 -070048#error filesystem not available
Vernon Mauery185b9f82018-07-20 10:52:36 -070049#endif
Patrick Venture0b02be92018-08-31 11:55:55 -070050
Patrick Venture0b02be92018-08-31 11:55:55 -070051// Defines
52#define SET_PARM_VERSION 0x01
Vernon Mauery1181af72018-10-08 12:05:00 -070053#define SET_PARM_BOOT_FLAGS_PERMANENT 0x40
54#define SET_PARM_BOOT_FLAGS_VALID_ONE_TIME 0x80
55#define SET_PARM_BOOT_FLAGS_VALID_PERMANENT 0xC0
ratagupta6f6bff2016-04-04 06:20:11 -050056
Vernon Mauery1181af72018-10-08 12:05:00 -070057std::unique_ptr<phosphor::Timer> identifyTimer = nullptr;
Marri Devender Rao6706c1c2018-05-14 00:29:38 -050058
Patrick Venture0b02be92018-08-31 11:55:55 -070059constexpr size_t SIZE_MAC = 18;
60constexpr size_t SIZE_BOOT_OPTION = (uint8_t)
61 BootOptionResponseSize::OPAL_NETWORK_SETTINGS; // Maximum size of the boot
62 // option parametrs
Ratan Guptafd28dd72016-08-01 04:58:01 -050063constexpr size_t SIZE_PREFIX = 7;
64constexpr size_t MAX_PREFIX_VALUE = 32;
65constexpr size_t SIZE_COOKIE = 4;
66constexpr size_t SIZE_VERSION = 2;
Tom Joseph5110c122018-03-23 17:55:40 +053067constexpr size_t DEFAULT_IDENTIFY_TIME_OUT = 15;
Ratan Gupta6ec7daa2017-07-15 14:13:01 +053068
Patrick Venture0b02be92018-08-31 11:55:55 -070069// PetiBoot-Specific
Ratan Gupta6ec7daa2017-07-15 14:13:01 +053070static constexpr uint8_t net_conf_initial_bytes[] = {0x80, 0x21, 0x70, 0x62,
Patrick Venture0b02be92018-08-31 11:55:55 -070071 0x21, 0x00, 0x01, 0x06};
Ratan Guptafd28dd72016-08-01 04:58:01 -050072
73static constexpr size_t COOKIE_OFFSET = 1;
74static constexpr size_t VERSION_OFFSET = 5;
Ratan Gupta6ec7daa2017-07-15 14:13:01 +053075static constexpr size_t ADDR_SIZE_OFFSET = 8;
Ratan Guptafd28dd72016-08-01 04:58:01 -050076static constexpr size_t MAC_OFFSET = 9;
77static constexpr size_t ADDRTYPE_OFFSET = 16;
78static constexpr size_t IPADDR_OFFSET = 17;
ratagupta6f6bff2016-04-04 06:20:11 -050079
Marri Devender Rao6706c1c2018-05-14 00:29:38 -050080static constexpr size_t encIdentifyObjectsSize = 1;
81static constexpr size_t chassisIdentifyReqLength = 2;
82static constexpr size_t identifyIntervalPos = 0;
83static constexpr size_t forceIdentifyPos = 1;
shgoupfd84fbbf2015-12-17 10:05:51 +080084
Adriana Kobylak40814c62015-10-27 15:58:44 -050085void register_netfn_chassis_functions() __attribute__((constructor));
86
shgoupfd84fbbf2015-12-17 10:05:51 +080087// Host settings in dbus
88// Service name should be referenced by connection name got via object mapper
Patrick Venture0b02be92018-08-31 11:55:55 -070089const char* settings_object_name = "/org/openbmc/settings/host0";
90const char* settings_intf_name = "org.freedesktop.DBus.Properties";
91const char* host_intf_name = "org.openbmc.settings.Host";
92const char* identify_led_object_name =
Tom Joseph5110c122018-03-23 17:55:40 +053093 "/xyz/openbmc_project/led/groups/enclosure_identify";
shgoupfd84fbbf2015-12-17 10:05:51 +080094
Ratan Guptadcb10672017-07-10 10:33:50 +053095constexpr auto SETTINGS_ROOT = "/";
96constexpr auto SETTINGS_MATCH = "host0";
Ratan Guptadcb10672017-07-10 10:33:50 +053097
98constexpr auto IP_INTERFACE = "xyz.openbmc_project.Network.IP";
99constexpr auto MAC_INTERFACE = "xyz.openbmc_project.Network.MACAddress";
100
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -0500101static constexpr auto chassisStateRoot = "/xyz/openbmc_project/state";
102static constexpr auto chassisPOHStateIntf =
Patrick Venture0b02be92018-08-31 11:55:55 -0700103 "xyz.openbmc_project.State.PowerOnHours";
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -0500104static constexpr auto pOHCounterProperty = "POHCounter";
105static constexpr auto match = "chassis0";
Ratan Guptadcb10672017-07-10 10:33:50 +0530106
Nan Li8d15fb42016-08-16 22:29:40 +0800107typedef struct
108{
109 uint8_t cap_flags;
110 uint8_t fru_info_dev_addr;
111 uint8_t sdr_dev_addr;
112 uint8_t sel_dev_addr;
113 uint8_t system_management_dev_addr;
114 uint8_t bridge_dev_addr;
Patrick Venture0b02be92018-08-31 11:55:55 -0700115} __attribute__((packed)) ipmi_chassis_cap_t;
Nan Li8d15fb42016-08-16 22:29:40 +0800116
Nan Lifdd8ec52016-08-28 03:57:40 +0800117typedef struct
118{
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500119 uint8_t cur_power_state;
120 uint8_t last_power_event;
121 uint8_t misc_power_state;
122 uint8_t front_panel_button_cap_status;
Patrick Venture0b02be92018-08-31 11:55:55 -0700123} __attribute__((packed)) ipmi_get_chassis_status_t;
Nan Lifdd8ec52016-08-28 03:57:40 +0800124
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -0500125/**
126 * @struct Get POH counter command response data
127 */
128struct GetPOHCountResponse
129{
Patrick Venture0b02be92018-08-31 11:55:55 -0700130 uint8_t minPerCount; ///< Minutes per count
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -0500131 uint8_t counterReading[4]; ///< Counter reading
Patrick Venture0b02be92018-08-31 11:55:55 -0700132} __attribute__((packed));
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -0500133
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530134// Phosphor Host State manager
135namespace State = sdbusplus::xyz::openbmc_project::State::server;
136
Vernon Mauery185b9f82018-07-20 10:52:36 -0700137namespace fs = std::filesystem;
Andrew Geisslera6e3a302017-05-31 19:34:00 -0500138
Ratan Guptadcb10672017-07-10 10:33:50 +0530139using namespace phosphor::logging;
140using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Marri Devender Rao81719702018-05-07 00:53:48 -0500141using namespace sdbusplus::xyz::openbmc_project::Control::Boot::server;
William A. Kennington III4c008022018-10-12 17:18:14 -0700142namespace variant_ns = sdbusplus::message::variant_ns;
143
Deepak Kodihalli8cc19362017-07-21 11:18:38 -0500144namespace chassis
145{
146namespace internal
147{
148
149constexpr auto bootModeIntf = "xyz.openbmc_project.Control.Boot.Mode";
150constexpr auto bootSourceIntf = "xyz.openbmc_project.Control.Boot.Source";
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500151constexpr auto powerRestoreIntf =
152 "xyz.openbmc_project.Control.Power.RestorePolicy";
Deepak Kodihalli8cc19362017-07-21 11:18:38 -0500153sdbusplus::bus::bus dbus(ipmid_get_sd_bus_connection());
154
155namespace cache
156{
157
158settings::Objects objects(dbus,
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500159 {bootModeIntf, bootSourceIntf, powerRestoreIntf});
Deepak Kodihalli8cc19362017-07-21 11:18:38 -0500160
161} // namespace cache
162} // namespace internal
163} // namespace chassis
164
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -0500165namespace poh
166{
167
168constexpr auto minutesPerCount = 60;
169
170} // namespace poh
171
Patrick Venture0b02be92018-08-31 11:55:55 -0700172// TODO : Can remove the below function as we have
Ratan Guptadcb10672017-07-10 10:33:50 +0530173// new functions which uses sdbusplus.
174//
175// openbmc/openbmc#1489
Patrick Venture0b02be92018-08-31 11:55:55 -0700176int dbus_get_property(const char* name, char** buf)
shgoupfd84fbbf2015-12-17 10:05:51 +0800177{
178 sd_bus_error error = SD_BUS_ERROR_NULL;
Patrick Venture0b02be92018-08-31 11:55:55 -0700179 sd_bus_message* m = NULL;
180 sd_bus* bus = NULL;
181 char* temp_buf = NULL;
182 char* connection = NULL;
shgoupfd84fbbf2015-12-17 10:05:51 +0800183 int r;
184
Brad Bishop35518682016-07-22 08:35:41 -0400185 // Get the system bus where most system services are provided.
186 bus = ipmid_get_sd_bus_connection();
shgoupfd84fbbf2015-12-17 10:05:51 +0800187
Brad Bishop35518682016-07-22 08:35:41 -0400188 r = mapper_get_service(bus, settings_object_name, &connection);
Patrick Venture0b02be92018-08-31 11:55:55 -0700189 if (r < 0)
190 {
Aditya Saripalli5fb14602017-11-09 14:46:27 +0530191 log<level::ERR>("Failed to get connection",
192 entry("OBJ_NAME=%s", settings_object_name),
193 entry("ERRNO=0x%X", -r));
shgoupfd84fbbf2015-12-17 10:05:51 +0800194 goto finish;
195 }
196
shgoupfd84fbbf2015-12-17 10:05:51 +0800197 /*
198 * Bus, service, object path, interface and method are provided to call
199 * the method.
200 * Signatures and input arguments are provided by the arguments at the
201 * end.
202 */
Patrick Venture0b02be92018-08-31 11:55:55 -0700203 r = sd_bus_call_method(bus, connection, /* service to contact */
204 settings_object_name, /* object path */
205 settings_intf_name, /* interface name */
206 "Get", /* method name */
207 &error, /* object to return error in */
208 &m, /* return message on success */
209 "ss", /* input signature */
210 host_intf_name, /* first argument */
211 name); /* second argument */
shgoupfd84fbbf2015-12-17 10:05:51 +0800212
Patrick Venture0b02be92018-08-31 11:55:55 -0700213 if (r < 0)
214 {
215 log<level::ERR>("Failed to issue Get method call",
Aditya Saripalli5fb14602017-11-09 14:46:27 +0530216 entry("ERRNO=0x%X", r));
shgoupfd84fbbf2015-12-17 10:05:51 +0800217 goto finish;
218 }
219
Patrick Venture0b02be92018-08-31 11:55:55 -0700220 /*
221 * The output should be parsed exactly the same as the output formatting
222 * specified.
223 */
224 r = sd_bus_message_read(m, "v", "s", &temp_buf);
225 if (r < 0)
226 {
227 log<level::ERR>("Failed to parse response message",
228 entry("ERRNO=0x%X", -r));
229 goto finish;
230 }
231
232 *buf = strdup(temp_buf);
233 /* *buf = (char*) malloc(strlen(temp_buf));
234 if (*buf) {
235 strcpy(*buf, temp_buf);
236 }
237 */
238
239finish:
shgoupfd84fbbf2015-12-17 10:05:51 +0800240 sd_bus_error_free(&error);
241 sd_bus_message_unref(m);
242 free(connection);
243
244 return r;
245}
246
Patrick Venture0b02be92018-08-31 11:55:55 -0700247// TODO : Can remove the below function as we have
248// new functions which uses sdbusplus.
249//
250// openbmc/openbmc#1489
251
252int dbus_set_property(const char* name, const char* value)
253{
254 sd_bus_error error = SD_BUS_ERROR_NULL;
255 sd_bus_message* m = NULL;
256 sd_bus* bus = NULL;
257 char* connection = NULL;
258 int r;
259
260 // Get the system bus where most system services are provided.
261 bus = ipmid_get_sd_bus_connection();
262
263 r = mapper_get_service(bus, settings_object_name, &connection);
264 if (r < 0)
265 {
266 log<level::ERR>("Failed to get connection",
267 entry("OBJ_NAME=%s", settings_object_name),
268 entry("ERRNO=0x%X", -r));
269 goto finish;
270 }
271
272 /*
273 * Bus, service, object path, interface and method are provided to call
274 * the method.
275 * Signatures and input arguments are provided by the arguments at the
276 * end.
277 */
278 r = sd_bus_call_method(bus, connection, /* service to contact */
279 settings_object_name, /* object path */
280 settings_intf_name, /* interface name */
281 "Set", /* method name */
282 &error, /* object to return error in */
283 &m, /* return message on success */
284 "ssv", /* input signature */
285 host_intf_name, /* first argument */
286 name, /* second argument */
287 "s", /* third argument */
288 value); /* fourth argument */
289
290 if (r < 0)
291 {
292 log<level::ERR>("Failed to issue Set method call",
293 entry("ERRNO=0x%X", r));
294 goto finish;
295 }
296
297finish:
298 sd_bus_error_free(&error);
299 sd_bus_message_unref(m);
300 free(connection);
301
302 return r;
303}
304
305struct get_sys_boot_options_t
306{
Adriana Kobylak40814c62015-10-27 15:58:44 -0500307 uint8_t parameter;
308 uint8_t set;
309 uint8_t block;
Patrick Venture0b02be92018-08-31 11:55:55 -0700310} __attribute__((packed));
Adriana Kobylak40814c62015-10-27 15:58:44 -0500311
Patrick Venture0b02be92018-08-31 11:55:55 -0700312struct get_sys_boot_options_response_t
313{
shgoupfd84fbbf2015-12-17 10:05:51 +0800314 uint8_t version;
315 uint8_t parm;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500316 uint8_t data[SIZE_BOOT_OPTION];
Patrick Venture0b02be92018-08-31 11:55:55 -0700317} __attribute__((packed));
shgoupfd84fbbf2015-12-17 10:05:51 +0800318
Patrick Venture0b02be92018-08-31 11:55:55 -0700319struct set_sys_boot_options_t
320{
shgoupfd84fbbf2015-12-17 10:05:51 +0800321 uint8_t parameter;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500322 uint8_t data[SIZE_BOOT_OPTION];
Patrick Venture0b02be92018-08-31 11:55:55 -0700323} __attribute__((packed));
Ratan Guptafd28dd72016-08-01 04:58:01 -0500324
Ratan Guptadcb10672017-07-10 10:33:50 +0530325int getHostNetworkData(get_sys_boot_options_response_t* respptr)
Ratan Guptafd28dd72016-08-01 04:58:01 -0500326{
Ratan Guptadcb10672017-07-10 10:33:50 +0530327 ipmi::PropertyMap properties;
328 int rc = 0;
Ratan Gupta8c31d232017-08-13 05:49:43 +0530329 uint8_t addrSize = ipmi::network::IPV4_ADDRESS_SIZE_BYTE;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500330
Ratan Guptadcb10672017-07-10 10:33:50 +0530331 try
332 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700333 // TODO There may be cases where an interface is implemented by multiple
Ratan Guptadcb10672017-07-10 10:33:50 +0530334 // objects,to handle such cases we are interested on that object
335 // which are on interested busname.
336 // Currenlty mapper doesn't give the readable busname(gives busid)
337 // so we can't match with bus name so giving some object specific info
338 // as SETTINGS_MATCH.
339 // Later SETTINGS_MATCH will be replaced with busname.
Ratan Guptafd28dd72016-08-01 04:58:01 -0500340
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530341 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
Ratan Guptadcb10672017-07-10 10:33:50 +0530342
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530343 auto ipObjectInfo = ipmi::getDbusObject(bus, IP_INTERFACE,
344 SETTINGS_ROOT, SETTINGS_MATCH);
345
346 auto macObjectInfo = ipmi::getDbusObject(bus, MAC_INTERFACE,
347 SETTINGS_ROOT, SETTINGS_MATCH);
348
Patrick Venture0b02be92018-08-31 11:55:55 -0700349 properties = ipmi::getAllDbusProperties(
350 bus, ipObjectInfo.second, ipObjectInfo.first, IP_INTERFACE);
351 auto variant = ipmi::getDbusProperty(bus, macObjectInfo.second,
352 macObjectInfo.first, MAC_INTERFACE,
353 "MACAddress");
Ratan Guptadcb10672017-07-10 10:33:50 +0530354
William A. Kennington III4c008022018-10-12 17:18:14 -0700355 auto ipAddress = variant_ns::get<std::string>(properties["Address"]);
Ratan Guptad70f4532017-08-04 02:07:31 +0530356
William A. Kennington III4c008022018-10-12 17:18:14 -0700357 auto gateway = variant_ns::get<std::string>(properties["Gateway"]);
Ratan Guptad70f4532017-08-04 02:07:31 +0530358
William A. Kennington III4c008022018-10-12 17:18:14 -0700359 auto prefix = variant_ns::get<uint8_t>(properties["PrefixLength"]);
Ratan Guptad70f4532017-08-04 02:07:31 +0530360
Patrick Venture0b02be92018-08-31 11:55:55 -0700361 uint8_t isStatic =
William A. Kennington III4c008022018-10-12 17:18:14 -0700362 (variant_ns::get<std::string>(properties["Origin"]) ==
Patrick Venture0b02be92018-08-31 11:55:55 -0700363 "xyz.openbmc_project.Network.IP.AddressOrigin.Static")
364 ? 1
365 : 0;
Ratan Guptad70f4532017-08-04 02:07:31 +0530366
William A. Kennington III4c008022018-10-12 17:18:14 -0700367 auto MACAddress = variant_ns::get<std::string>(variant);
Ratan Guptacc8feb42017-07-25 21:52:10 +0530368
Ratan Guptad70f4532017-08-04 02:07:31 +0530369 // it is expected here that we should get the valid data
370 // but we may also get the default values.
371 // Validation of the data is done by settings.
372 //
373 // if mac address is default mac address then
374 // don't send blank override.
Ratan Gupta8c31d232017-08-13 05:49:43 +0530375 if ((MACAddress == ipmi::network::DEFAULT_MAC_ADDRESS))
Ratan Guptad70f4532017-08-04 02:07:31 +0530376 {
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700377 std::memset(respptr->data, 0, SIZE_BOOT_OPTION);
Ratan Guptad70f4532017-08-04 02:07:31 +0530378 rc = -1;
379 return rc;
380 }
381 // if addr is static then ipaddress,gateway,prefix
382 // should not be default one,don't send blank override.
383 if (isStatic)
384 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700385 if ((ipAddress == ipmi::network::DEFAULT_ADDRESS) ||
386 (gateway == ipmi::network::DEFAULT_ADDRESS) || (!prefix))
Ratan Guptad70f4532017-08-04 02:07:31 +0530387 {
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700388 std::memset(respptr->data, 0, SIZE_BOOT_OPTION);
Ratan Guptad70f4532017-08-04 02:07:31 +0530389 rc = -1;
390 return rc;
391 }
392 }
393
Patrick Venture0b02be92018-08-31 11:55:55 -0700394 sscanf(
395 MACAddress.c_str(), ipmi::network::MAC_ADDRESS_FORMAT,
396 (respptr->data + MAC_OFFSET), (respptr->data + MAC_OFFSET + 1),
397 (respptr->data + MAC_OFFSET + 2), (respptr->data + MAC_OFFSET + 3),
398 (respptr->data + MAC_OFFSET + 4), (respptr->data + MAC_OFFSET + 5));
Ratan Guptadcb10672017-07-10 10:33:50 +0530399
Ratan Guptadcb10672017-07-10 10:33:50 +0530400 respptr->data[MAC_OFFSET + 6] = 0x00;
401
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700402 std::memcpy(respptr->data + ADDRTYPE_OFFSET, &isStatic,
403 sizeof(isStatic));
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530404
William A. Kennington III4c008022018-10-12 17:18:14 -0700405 uint8_t addressFamily =
406 (variant_ns::get<std::string>(properties["Type"]) ==
407 "xyz.openbmc_project.Network.IP.Protocol.IPv4")
408 ? AF_INET
409 : AF_INET6;
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530410
Patrick Venture0b02be92018-08-31 11:55:55 -0700411 addrSize = (addressFamily == AF_INET)
412 ? ipmi::network::IPV4_ADDRESS_SIZE_BYTE
413 : ipmi::network::IPV6_ADDRESS_SIZE_BYTE;
Ratan Guptadcb10672017-07-10 10:33:50 +0530414
415 // ipaddress and gateway would be in IPv4 format
Ratan Guptad70f4532017-08-04 02:07:31 +0530416 inet_pton(addressFamily, ipAddress.c_str(),
Patrick Venture0b02be92018-08-31 11:55:55 -0700417 (respptr->data + IPADDR_OFFSET));
Ratan Guptadcb10672017-07-10 10:33:50 +0530418
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530419 uint8_t prefixOffset = IPADDR_OFFSET + addrSize;
420
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700421 std::memcpy(respptr->data + prefixOffset, &prefix, sizeof(prefix));
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530422
423 uint8_t gatewayOffset = prefixOffset + sizeof(decltype(prefix));
424
Ratan Guptad70f4532017-08-04 02:07:31 +0530425 inet_pton(addressFamily, gateway.c_str(),
Patrick Venture0b02be92018-08-31 11:55:55 -0700426 (respptr->data + gatewayOffset));
Ratan Guptadcb10672017-07-10 10:33:50 +0530427 }
428 catch (InternalFailure& e)
429 {
430 commit<InternalFailure>();
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700431 std::memset(respptr->data, 0, SIZE_BOOT_OPTION);
Ratan Guptadcb10672017-07-10 10:33:50 +0530432 rc = -1;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500433 return rc;
434 }
435
Patrick Venture0b02be92018-08-31 11:55:55 -0700436 // PetiBoot-Specific
437 // If success then copy the first 9 bytes to the data
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700438 std::memcpy(respptr->data, net_conf_initial_bytes,
439 sizeof(net_conf_initial_bytes));
Ratan Guptafd28dd72016-08-01 04:58:01 -0500440
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700441 std::memcpy(respptr->data + ADDR_SIZE_OFFSET, &addrSize, sizeof(addrSize));
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530442
Ratan Guptafd28dd72016-08-01 04:58:01 -0500443#ifdef _IPMI_DEBUG_
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700444 std::printf("\n===Printing the IPMI Formatted Data========\n");
Ratan Guptafd28dd72016-08-01 04:58:01 -0500445
Ratan Guptadcb10672017-07-10 10:33:50 +0530446 for (uint8_t pos = 0; pos < index; pos++)
447 {
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700448 std::printf("%02x ", respptr->data[pos]);
Ratan Guptadcb10672017-07-10 10:33:50 +0530449 }
Ratan Guptafd28dd72016-08-01 04:58:01 -0500450#endif
451
Ratan Guptafd28dd72016-08-01 04:58:01 -0500452 return rc;
453}
454
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530455/** @brief convert IPv4 and IPv6 addresses from binary to text form.
456 * @param[in] family - IPv4/Ipv6
457 * @param[in] data - req data pointer.
458 * @param[in] offset - offset in the data.
459 * @param[in] addrSize - size of the data which needs to be read from offset.
460 * @returns address in text form.
461 */
462
Patrick Venture0b02be92018-08-31 11:55:55 -0700463std::string getAddrStr(uint8_t family, uint8_t* data, uint8_t offset,
464 uint8_t addrSize)
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530465{
466 char ipAddr[INET6_ADDRSTRLEN] = {};
467
Patrick Venture0b02be92018-08-31 11:55:55 -0700468 switch (family)
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530469 {
470 case AF_INET:
471 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700472 struct sockaddr_in addr4
473 {
474 };
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700475 std::memcpy(&addr4.sin_addr.s_addr, &data[offset], addrSize);
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530476
Patrick Venture0b02be92018-08-31 11:55:55 -0700477 inet_ntop(AF_INET, &addr4.sin_addr, ipAddr, INET_ADDRSTRLEN);
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530478
479 break;
480 }
481 case AF_INET6:
482 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700483 struct sockaddr_in6 addr6
484 {
485 };
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700486 std::memcpy(&addr6.sin6_addr.s6_addr, &data[offset], addrSize);
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530487
Patrick Venture0b02be92018-08-31 11:55:55 -0700488 inet_ntop(AF_INET6, &addr6.sin6_addr, ipAddr, INET6_ADDRSTRLEN);
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530489
490 break;
491 }
492 default:
493 {
494 return {};
495 }
496 }
497
498 return ipAddr;
499}
500
Ratan Guptadcb10672017-07-10 10:33:50 +0530501int setHostNetworkData(set_sys_boot_options_t* reqptr)
Ratan Guptafd28dd72016-08-01 04:58:01 -0500502{
Ratan Guptadcb10672017-07-10 10:33:50 +0530503 using namespace std::string_literals;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500504 std::string host_network_config;
Patrick Venture0b02be92018-08-31 11:55:55 -0700505 char mac[]{"00:00:00:00:00:00"};
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530506 std::string ipAddress, gateway;
Patrick Venture0b02be92018-08-31 11:55:55 -0700507 char addrOrigin{0};
508 uint8_t addrSize{0};
Ratan Guptadcb10672017-07-10 10:33:50 +0530509 std::string addressOrigin =
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530510 "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP";
Patrick Venture0b02be92018-08-31 11:55:55 -0700511 std::string addressType = "xyz.openbmc_project.Network.IP.Protocol.IPv4";
512 uint8_t prefix{0};
Ratan Guptadcb10672017-07-10 10:33:50 +0530513 uint32_t zeroCookie = 0;
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530514 uint8_t family = AF_INET;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500515
Patrick Venture0b02be92018-08-31 11:55:55 -0700516 // cookie starts from second byte
Ratan Guptafd28dd72016-08-01 04:58:01 -0500517 // version starts from sixth byte
518
Ratan Guptadcb10672017-07-10 10:33:50 +0530519 try
Ratan Guptafd28dd72016-08-01 04:58:01 -0500520 {
Ratan Guptadcb10672017-07-10 10:33:50 +0530521 do
522 {
523 // cookie == 0x21 0x70 0x62 0x21
524 if (memcmp(&(reqptr->data[COOKIE_OFFSET]),
Patrick Venture0b02be92018-08-31 11:55:55 -0700525 (net_conf_initial_bytes + COOKIE_OFFSET),
526 SIZE_COOKIE) != 0)
Ratan Guptadcb10672017-07-10 10:33:50 +0530527 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700528 // cookie == 0
529 if (memcmp(&(reqptr->data[COOKIE_OFFSET]), &zeroCookie,
530 SIZE_COOKIE) == 0)
Ratan Guptadcb10672017-07-10 10:33:50 +0530531 {
532 // need to zero out the network settings.
533 break;
534 }
535
536 log<level::ERR>("Invalid Cookie");
537 elog<InternalFailure>();
538 }
539
540 // vesion == 0x00 0x01
541 if (memcmp(&(reqptr->data[VERSION_OFFSET]),
Patrick Venture0b02be92018-08-31 11:55:55 -0700542 (net_conf_initial_bytes + VERSION_OFFSET),
543 SIZE_VERSION) != 0)
Ratan Guptadcb10672017-07-10 10:33:50 +0530544 {
545
546 log<level::ERR>("Invalid Version");
547 elog<InternalFailure>();
548 }
549
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700550 std::snprintf(
551 mac, SIZE_MAC, ipmi::network::MAC_ADDRESS_FORMAT,
552 reqptr->data[MAC_OFFSET], reqptr->data[MAC_OFFSET + 1],
553 reqptr->data[MAC_OFFSET + 2], reqptr->data[MAC_OFFSET + 3],
554 reqptr->data[MAC_OFFSET + 4], reqptr->data[MAC_OFFSET + 5]);
Ratan Guptadcb10672017-07-10 10:33:50 +0530555
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700556 std::memcpy(&addrOrigin, &(reqptr->data[ADDRTYPE_OFFSET]),
557 sizeof(decltype(addrOrigin)));
Ratan Guptadcb10672017-07-10 10:33:50 +0530558
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530559 if (addrOrigin)
Ratan Guptadcb10672017-07-10 10:33:50 +0530560 {
561 addressOrigin =
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530562 "xyz.openbmc_project.Network.IP.AddressOrigin.Static";
Ratan Guptadcb10672017-07-10 10:33:50 +0530563 }
564
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530565 // Get the address size
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700566 std::memcpy(&addrSize, &reqptr->data[ADDR_SIZE_OFFSET],
567 sizeof(addrSize));
Ratan Guptadcb10672017-07-10 10:33:50 +0530568
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530569 uint8_t prefixOffset = IPADDR_OFFSET + addrSize;
Ratan Guptadcb10672017-07-10 10:33:50 +0530570
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700571 std::memcpy(&prefix, &(reqptr->data[prefixOffset]),
572 sizeof(decltype(prefix)));
Ratan Guptadcb10672017-07-10 10:33:50 +0530573
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530574 uint8_t gatewayOffset = prefixOffset + sizeof(decltype(prefix));
575
Ratan Gupta8c31d232017-08-13 05:49:43 +0530576 if (addrSize != ipmi::network::IPV4_ADDRESS_SIZE_BYTE)
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530577 {
578 addressType = "xyz.openbmc_project.Network.IP.Protocol.IPv6";
579 family = AF_INET6;
580 }
581
Patrick Venture0b02be92018-08-31 11:55:55 -0700582 ipAddress =
583 getAddrStr(family, reqptr->data, IPADDR_OFFSET, addrSize);
Ratan Guptad70f4532017-08-04 02:07:31 +0530584
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530585 gateway = getAddrStr(family, reqptr->data, gatewayOffset, addrSize);
586
Patrick Venture0b02be92018-08-31 11:55:55 -0700587 } while (0);
Ratan Guptadcb10672017-07-10 10:33:50 +0530588
Patrick Venture0b02be92018-08-31 11:55:55 -0700589 // Cookie == 0 or it is a valid cookie
590 host_network_config += "ipaddress="s + ipAddress + ",prefix="s +
591 std::to_string(prefix) + ",gateway="s + gateway +
592 ",mac="s + mac + ",addressOrigin="s +
593 addressOrigin;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500594
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530595 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
596
597 auto ipObjectInfo = ipmi::getDbusObject(bus, IP_INTERFACE,
598 SETTINGS_ROOT, SETTINGS_MATCH);
599 auto macObjectInfo = ipmi::getDbusObject(bus, MAC_INTERFACE,
600 SETTINGS_ROOT, SETTINGS_MATCH);
Ratan Guptadcb10672017-07-10 10:33:50 +0530601 // set the dbus property
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530602 ipmi::setDbusProperty(bus, ipObjectInfo.second, ipObjectInfo.first,
Patrick Venture0b02be92018-08-31 11:55:55 -0700603 IP_INTERFACE, "Address", std::string(ipAddress));
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530604 ipmi::setDbusProperty(bus, ipObjectInfo.second, ipObjectInfo.first,
Patrick Venture0b02be92018-08-31 11:55:55 -0700605 IP_INTERFACE, "PrefixLength", prefix);
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530606 ipmi::setDbusProperty(bus, ipObjectInfo.second, ipObjectInfo.first,
Patrick Venture0b02be92018-08-31 11:55:55 -0700607 IP_INTERFACE, "Origin", addressOrigin);
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530608 ipmi::setDbusProperty(bus, ipObjectInfo.second, ipObjectInfo.first,
Patrick Venture0b02be92018-08-31 11:55:55 -0700609 IP_INTERFACE, "Gateway", std::string(gateway));
610 ipmi::setDbusProperty(
611 bus, ipObjectInfo.second, ipObjectInfo.first, IP_INTERFACE, "Type",
612 std::string("xyz.openbmc_project.Network.IP.Protocol.IPv4"));
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530613 ipmi::setDbusProperty(bus, macObjectInfo.second, macObjectInfo.first,
Patrick Venture0b02be92018-08-31 11:55:55 -0700614 MAC_INTERFACE, "MACAddress", std::string(mac));
Ratan Guptafd28dd72016-08-01 04:58:01 -0500615
Patrick Venture0b02be92018-08-31 11:55:55 -0700616 log<level::DEBUG>(
617 "Network configuration changed",
618 entry("NETWORKCONFIG=%s", host_network_config.c_str()));
Ratan Guptafd28dd72016-08-01 04:58:01 -0500619 }
Ratan Guptadcb10672017-07-10 10:33:50 +0530620 catch (InternalFailure& e)
621 {
622 commit<InternalFailure>();
623 return -1;
624 }
625
626 return 0;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500627}
628
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -0500629uint32_t getPOHCounter()
630{
631 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
632
Patrick Venture0b02be92018-08-31 11:55:55 -0700633 auto chassisStateObj =
634 ipmi::getDbusObject(bus, chassisPOHStateIntf, chassisStateRoot, match);
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -0500635
Patrick Venture0b02be92018-08-31 11:55:55 -0700636 auto service =
637 ipmi::getService(bus, chassisPOHStateIntf, chassisStateObj.first);
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -0500638
Patrick Venture0b02be92018-08-31 11:55:55 -0700639 auto propValue =
640 ipmi::getDbusProperty(bus, service, chassisStateObj.first,
641 chassisPOHStateIntf, pOHCounterProperty);
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -0500642
William A. Kennington III4c008022018-10-12 17:18:14 -0700643 return variant_ns::get<uint32_t>(propValue);
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -0500644}
645
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500646ipmi_ret_t ipmi_chassis_wildcard(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
647 ipmi_request_t request,
648 ipmi_response_t response,
649 ipmi_data_len_t data_len,
650 ipmi_context_t context)
Adriana Kobylak40814c62015-10-27 15:58:44 -0500651{
Adriana Kobylak40814c62015-10-27 15:58:44 -0500652 // Status code.
Nan Li70aa8d92016-08-29 00:11:10 +0800653 ipmi_ret_t rc = IPMI_CC_INVALID;
Adriana Kobylak40814c62015-10-27 15:58:44 -0500654 *data_len = 0;
655 return rc;
656}
657
Nan Li8d15fb42016-08-16 22:29:40 +0800658ipmi_ret_t ipmi_get_chassis_cap(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Patrick Venture0b02be92018-08-31 11:55:55 -0700659 ipmi_request_t request,
660 ipmi_response_t response,
661 ipmi_data_len_t data_len,
662 ipmi_context_t context)
Nan Li8d15fb42016-08-16 22:29:40 +0800663{
664 // sd_bus error
665 ipmi_ret_t rc = IPMI_CC_OK;
666
667 ipmi_chassis_cap_t chassis_cap{};
668
669 *data_len = sizeof(ipmi_chassis_cap_t);
670
671 // TODO: need future work. Get those flag from MRW.
672
673 // capabilities flags
674 // [7..4] - reserved
675 // [3] – 1b = provides power interlock (IPM 1.5)
676 // [2] – 1b = provides Diagnostic Interrupt (FP NMI)
Patrick Venture0b02be92018-08-31 11:55:55 -0700677 // [1] – 1b = provides “Front Panel Lockout” (indicates that the chassis has
678 // capabilities
679 // to lock out external power control and reset button or front
680 // panel interfaces and/or detect tampering with those
681 // interfaces).
Nan Li8d15fb42016-08-16 22:29:40 +0800682 // [0] -1b = Chassis provides intrusion (physical security) sensor.
683 // set to default value 0x0.
684 chassis_cap.cap_flags = 0x0;
685
686 // Since we do not have a separate SDR Device/SEL Device/ FRU repository.
687 // The 20h was given as those 5 device addresses.
688 // Chassis FRU info Device Address
689 chassis_cap.fru_info_dev_addr = 0x20;
690
691 // Chassis SDR Device Address
692 chassis_cap.sdr_dev_addr = 0x20;
693
694 // Chassis SEL Device Address
695 chassis_cap.sel_dev_addr = 0x20;
696
697 // Chassis System Management Device Address
698 chassis_cap.system_management_dev_addr = 0x20;
699
700 // Chassis Bridge Device Address.
701 chassis_cap.bridge_dev_addr = 0x20;
702
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700703 std::memcpy(response, &chassis_cap, *data_len);
Nan Li8d15fb42016-08-16 22:29:40 +0800704
705 return rc;
706}
707
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530708//------------------------------------------
709// Calls into Host State Manager Dbus object
710//------------------------------------------
711int initiate_state_transition(State::Host::Transition transition)
vishwa36993272015-11-20 12:43:49 -0600712{
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500713 // OpenBMC Host State Manager dbus framework
Patrick Venture0b02be92018-08-31 11:55:55 -0700714 constexpr auto HOST_STATE_MANAGER_ROOT = "/xyz/openbmc_project/state/host0";
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500715 constexpr auto HOST_STATE_MANAGER_IFACE = "xyz.openbmc_project.State.Host";
Patrick Venture0b02be92018-08-31 11:55:55 -0700716 constexpr auto DBUS_PROPERTY_IFACE = "org.freedesktop.DBus.Properties";
717 constexpr auto PROPERTY = "RequestedHostTransition";
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530718
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500719 // sd_bus error
720 int rc = 0;
Patrick Venture0b02be92018-08-31 11:55:55 -0700721 char* busname = NULL;
vishwa36993272015-11-20 12:43:49 -0600722
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500723 // SD Bus error report mechanism.
724 sd_bus_error bus_error = SD_BUS_ERROR_NULL;
vishwa36993272015-11-20 12:43:49 -0600725
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500726 // Gets a hook onto either a SYSTEM or SESSION bus
Patrick Venture0b02be92018-08-31 11:55:55 -0700727 sd_bus* bus_type = ipmid_get_sd_bus_connection();
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500728 rc = mapper_get_service(bus_type, HOST_STATE_MANAGER_ROOT, &busname);
729 if (rc < 0)
730 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700731 log<level::ERR>(
732 "Failed to get bus name",
733 entry("ERRNO=0x%X, OBJPATH=%s", -rc, HOST_STATE_MANAGER_ROOT));
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500734 return rc;
735 }
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530736
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500737 // Convert to string equivalent of the passed in transition enum.
738 auto request = State::convertForMessage(transition);
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530739
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500740 rc = sd_bus_call_method(bus_type, // On the system bus
741 busname, // Service to contact
742 HOST_STATE_MANAGER_ROOT, // Object path
743 DBUS_PROPERTY_IFACE, // Interface name
744 "Set", // Method to be called
745 &bus_error, // object to return error
746 nullptr, // Response buffer if any
747 "ssv", // Takes 3 arguments
Patrick Venture0b02be92018-08-31 11:55:55 -0700748 HOST_STATE_MANAGER_IFACE, PROPERTY, "s",
749 request.c_str());
750 if (rc < 0)
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500751 {
752 log<level::ERR>("Failed to initiate transition",
Aditya Saripalli5fb14602017-11-09 14:46:27 +0530753 entry("ERRNO=0x%X, REQUEST=%s", -rc, request.c_str()));
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500754 }
755 else
756 {
757 log<level::INFO>("Transition request initiated successfully");
758 }
vishwa36993272015-11-20 12:43:49 -0600759
760 sd_bus_error_free(&bus_error);
Sergey Solomineb9b8142016-08-23 09:07:28 -0500761 free(busname);
vishwa36993272015-11-20 12:43:49 -0600762
Sergey Solomineb9b8142016-08-23 09:07:28 -0500763 return rc;
vishwa36993272015-11-20 12:43:49 -0600764}
765
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500766namespace power_policy
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500767{
Nan Lifdd8ec52016-08-28 03:57:40 +0800768
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500769using namespace sdbusplus::xyz::openbmc_project::Control::Power::server;
770using IpmiValue = uint8_t;
771using DbusValue = RestorePolicy::Policy;
Nan Lifdd8ec52016-08-28 03:57:40 +0800772
Patrick Venture0b02be92018-08-31 11:55:55 -0700773std::map<DbusValue, IpmiValue> dbusToIpmi = {
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500774 {RestorePolicy::Policy::AlwaysOff, 0x00},
775 {RestorePolicy::Policy::Restore, 0x01},
Patrick Venture0b02be92018-08-31 11:55:55 -0700776 {RestorePolicy::Policy::AlwaysOn, 0x02}};
Nan Lifdd8ec52016-08-28 03:57:40 +0800777
Yong Lic6713cf2018-09-12 12:35:13 +0800778static constexpr uint8_t noChange = 0x03;
779static constexpr uint8_t allSupport = 0x01 | 0x02 | 0x04;
780static constexpr uint8_t policyBitMask = 0x07;
781static constexpr uint8_t setPolicyReqLen = 1;
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500782} // namespace power_policy
Nan Lifdd8ec52016-08-28 03:57:40 +0800783
784//----------------------------------------------------------------------
785// Get Chassis Status commands
786//----------------------------------------------------------------------
787ipmi_ret_t ipmi_get_chassis_status(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500788 ipmi_request_t request,
789 ipmi_response_t response,
790 ipmi_data_len_t data_len,
791 ipmi_context_t context)
Nan Lifdd8ec52016-08-28 03:57:40 +0800792{
Patrick Venture0b02be92018-08-31 11:55:55 -0700793 const char* objname = "/org/openbmc/control/power0";
794 const char* intf = "org.openbmc.control.Power";
Nan Lifdd8ec52016-08-28 03:57:40 +0800795
Patrick Venture0b02be92018-08-31 11:55:55 -0700796 sd_bus* bus = NULL;
797 sd_bus_message* reply = NULL;
Nan Lifdd8ec52016-08-28 03:57:40 +0800798 int r = 0;
799 int pgood = 0;
Patrick Venture0b02be92018-08-31 11:55:55 -0700800 char* busname = NULL;
Nan Lifdd8ec52016-08-28 03:57:40 +0800801 ipmi_ret_t rc = IPMI_CC_OK;
802 ipmi_get_chassis_status_t chassis_status{};
803
Nan Lifdd8ec52016-08-28 03:57:40 +0800804 uint8_t s = 0;
805
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500806 using namespace chassis::internal;
807 using namespace chassis::internal::cache;
808 using namespace power_policy;
809
Deepak Kodihallie6027092017-08-27 08:13:37 -0500810 const auto& powerRestoreSetting = objects.map.at(powerRestoreIntf).front();
Patrick Venture0b02be92018-08-31 11:55:55 -0700811 auto method = dbus.new_method_call(
812 objects.service(powerRestoreSetting, powerRestoreIntf).c_str(),
813 powerRestoreSetting.c_str(), ipmi::PROP_INTF, "Get");
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500814 method.append(powerRestoreIntf, "PowerRestorePolicy");
815 auto resp = dbus.call(method);
816 if (resp.is_method_error())
817 {
818 log<level::ERR>("Error in PowerRestorePolicy Get");
819 report<InternalFailure>();
820 *data_len = 0;
821 return IPMI_CC_UNSPECIFIED_ERROR;
822 }
823 sdbusplus::message::variant<std::string> result;
824 resp.read(result);
William A. Kennington III4c008022018-10-12 17:18:14 -0700825 auto powerRestore = RestorePolicy::convertPolicyFromString(
826 variant_ns::get<std::string>(result));
Nan Lifdd8ec52016-08-28 03:57:40 +0800827
828 *data_len = 4;
829
Tom Joseph63a00512017-08-09 23:39:59 +0530830 bus = ipmid_get_sd_bus_connection();
831
Nan Lifdd8ec52016-08-28 03:57:40 +0800832 r = mapper_get_service(bus, objname, &busname);
Patrick Venture0b02be92018-08-31 11:55:55 -0700833 if (r < 0)
834 {
835 log<level::ERR>("Failed to get bus name", entry("ERRNO=0x%X", -r));
Nan Lifdd8ec52016-08-28 03:57:40 +0800836 rc = IPMI_CC_UNSPECIFIED_ERROR;
837 goto finish;
838 }
839
Patrick Venture0b02be92018-08-31 11:55:55 -0700840 r = sd_bus_get_property(bus, busname, objname, intf, "pgood", NULL, &reply,
841 "i");
842 if (r < 0)
843 {
Aditya Saripalli5fb14602017-11-09 14:46:27 +0530844 log<level::ERR>("Failed to call sd_bus_get_property",
Patrick Venture0b02be92018-08-31 11:55:55 -0700845 entry("PROPERTY=%s", "pgood"), entry("ERRNO=0x%X", -r),
846 entry("BUS=%s", busname), entry("PATH=%s", objname),
Aditya Saripalli5fb14602017-11-09 14:46:27 +0530847 entry("INTERFACE=%s", intf));
Nan Lifdd8ec52016-08-28 03:57:40 +0800848 rc = IPMI_CC_UNSPECIFIED_ERROR;
849 goto finish;
850 }
851
852 r = sd_bus_message_read(reply, "i", &pgood);
Patrick Venture0b02be92018-08-31 11:55:55 -0700853 if (r < 0)
854 {
855 log<level::ERR>("Failed to read sensor:", entry("ERRNO=0x%X", -r));
Nan Lifdd8ec52016-08-28 03:57:40 +0800856 rc = IPMI_CC_UNSPECIFIED_ERROR;
857 goto finish;
858 }
859
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500860 s = dbusToIpmi.at(powerRestore);
Nan Lifdd8ec52016-08-28 03:57:40 +0800861
862 // Current Power State
863 // [7] reserved
864 // [6..5] power restore policy
865 // 00b = chassis stays powered off after AC/mains returns
866 // 01b = after AC returns, power is restored to the state that was
867 // in effect when AC/mains was lost.
868 // 10b = chassis always powers up after AC/mains returns
869 // 11b = unknow
870 // Set to 00b, by observing the hardware behavior.
Patrick Venture0b02be92018-08-31 11:55:55 -0700871 // Do we need to define a dbus property to identify the restore
872 // policy?
Nan Lifdd8ec52016-08-28 03:57:40 +0800873
874 // [4] power control fault
875 // 1b = controller attempted to turn system power on or off, but
876 // system did not enter desired state.
877 // Set to 0b, since We don't support it..
878
879 // [3] power fault
880 // 1b = fault detected in main power subsystem.
881 // set to 0b. for we don't support it.
882
883 // [2] 1b = interlock (chassis is presently shut down because a chassis
884 // panel interlock switch is active). (IPMI 1.5)
885 // set to 0b, for we don't support it.
886
887 // [1] power overload
888 // 1b = system shutdown because of power overload condition.
889 // set to 0b, for we don't support it.
890
891 // [0] power is on
892 // 1b = system power is on
893 // 0b = system power is off(soft-off S4/S5, or mechanical off)
894
Patrick Venture0b02be92018-08-31 11:55:55 -0700895 chassis_status.cur_power_state = ((s & 0x3) << 5) | (pgood & 0x1);
Nan Lifdd8ec52016-08-28 03:57:40 +0800896
897 // Last Power Event
898 // [7..5] – reserved
899 // [4] – 1b = last ‘Power is on’ state was entered via IPMI command
900 // [3] – 1b = last power down caused by power fault
901 // [2] – 1b = last power down caused by a power interlock being activated
902 // [1] – 1b = last power down caused by a Power overload
903 // [0] – 1b = AC failed
904 // set to 0x0, for we don't support these fields.
905
906 chassis_status.last_power_event = 0;
907
908 // Misc. Chassis State
909 // [7] – reserved
910 // [6] – 1b = Chassis Identify command and state info supported (Optional)
911 // 0b = Chassis Identify command support unspecified via this command.
912 // (The Get Command Support command , if implemented, would still
913 // indicate support for the Chassis Identify command)
Patrick Venture0b02be92018-08-31 11:55:55 -0700914 // [5..4] – Chassis Identify State. Mandatory when bit[6] =1b, reserved
915 // (return
Nan Lifdd8ec52016-08-28 03:57:40 +0800916 // as 00b) otherwise. Returns the present chassis identify state.
917 // Refer to the Chassis Identify command for more info.
918 // 00b = chassis identify state = Off
919 // 01b = chassis identify state = Temporary(timed) On
920 // 10b = chassis identify state = Indefinite On
921 // 11b = reserved
922 // [3] – 1b = Cooling/fan fault detected
923 // [2] – 1b = Drive Fault
924 // [1] – 1b = Front Panel Lockout active (power off and reset via chassis
925 // push-buttons disabled.)
926 // [0] – 1b = Chassis Intrusion active
927 // set to 0, for we don't support them.
928 chassis_status.misc_power_state = 0;
929
930 // Front Panel Button Capabilities and disable/enable status(Optional)
931 // set to 0, for we don't support them.
932 chassis_status.front_panel_button_cap_status = 0;
933
934 // Pack the actual response
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700935 std::memcpy(response, &chassis_status, *data_len);
Nan Lifdd8ec52016-08-28 03:57:40 +0800936
937finish:
938 free(busname);
939 reply = sd_bus_message_unref(reply);
940
941 return rc;
942}
Chris Austen7888c4d2015-12-03 15:26:20 -0600943
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +0530944//-------------------------------------------------------------
945// Send a command to SoftPowerOff application to stop any timer
946//-------------------------------------------------------------
947int stop_soft_off_timer()
948{
Patrick Venture0b02be92018-08-31 11:55:55 -0700949 constexpr auto iface = "org.freedesktop.DBus.Properties";
950 constexpr auto soft_off_iface = "xyz.openbmc_project.Ipmi.Internal."
951 "SoftPowerOff";
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +0530952
Patrick Venture0b02be92018-08-31 11:55:55 -0700953 constexpr auto property = "ResponseReceived";
954 constexpr auto value = "xyz.openbmc_project.Ipmi.Internal."
955 "SoftPowerOff.HostResponse.HostShutdown";
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +0530956
957 // Get the system bus where most system services are provided.
958 auto bus = ipmid_get_sd_bus_connection();
959
960 // Get the service name
Andrew Geissler2b4e4592017-06-08 11:18:35 -0500961 // TODO openbmc/openbmc#1661 - Mapper refactor
962 //
963 // See openbmc/openbmc#1743 for some details but high level summary is that
964 // for now the code will directly call the soft off interface due to a
965 // race condition with mapper usage
966 //
Patrick Venture0b02be92018-08-31 11:55:55 -0700967 // char *busname = nullptr;
968 // auto r = mapper_get_service(bus, SOFTOFF_OBJPATH, &busname);
969 // if (r < 0)
Andrew Geissler2b4e4592017-06-08 11:18:35 -0500970 //{
971 // fprintf(stderr, "Failed to get %s bus name: %s\n",
Aditya Saripalli5fb14602017-11-09 14:46:27 +0530972 // SOFTOFF_OBJPATH, -r);
Andrew Geissler2b4e4592017-06-08 11:18:35 -0500973 // return r;
974 //}
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +0530975
976 // No error object or reply expected.
Andrew Geissler2b4e4592017-06-08 11:18:35 -0500977 int rc = sd_bus_call_method(bus, SOFTOFF_BUSNAME, SOFTOFF_OBJPATH, iface,
Patrick Venture0b02be92018-08-31 11:55:55 -0700978 "Set", nullptr, nullptr, "ssv", soft_off_iface,
979 property, "s", value);
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +0530980 if (rc < 0)
981 {
Aditya Saripalli5fb14602017-11-09 14:46:27 +0530982 log<level::ERR>("Failed to set property in SoftPowerOff object",
983 entry("ERRNO=0x%X", -rc));
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +0530984 }
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500985
Patrick Venture0b02be92018-08-31 11:55:55 -0700986 // TODO openbmc/openbmc#1661 - Mapper refactor
987 // free(busname);
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +0530988 return rc;
989}
990
vishwa36993272015-11-20 12:43:49 -0600991//----------------------------------------------------------------------
Andrew Geisslera6e3a302017-05-31 19:34:00 -0500992// Create file to indicate there is no need for softoff notification to host
993//----------------------------------------------------------------------
994void indicate_no_softoff_needed()
995{
996 fs::path path{HOST_INBAND_REQUEST_DIR};
997 if (!fs::is_directory(path))
998 {
999 fs::create_directory(path);
1000 }
1001
1002 // Add the host instance (default 0 for now) to the file name
1003 std::string file{HOST_INBAND_REQUEST_FILE};
Patrick Venture0b02be92018-08-31 11:55:55 -07001004 auto size = std::snprintf(nullptr, 0, file.c_str(), 0);
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001005 size++; // null
1006 std::unique_ptr<char[]> buf(new char[size]);
Patrick Venture0b02be92018-08-31 11:55:55 -07001007 std::snprintf(buf.get(), size, file.c_str(), 0);
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001008
1009 // Append file name to directory and create it
1010 path /= buf.get();
1011 std::ofstream(path.c_str());
1012}
1013
1014//----------------------------------------------------------------------
vishwa36993272015-11-20 12:43:49 -06001015// Chassis Control commands
1016//----------------------------------------------------------------------
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001017ipmi_ret_t ipmi_chassis_control(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1018 ipmi_request_t request,
1019 ipmi_response_t response,
1020 ipmi_data_len_t data_len,
1021 ipmi_context_t context)
vishwa36993272015-11-20 12:43:49 -06001022{
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001023 // Error from power off.
1024 int rc = 0;
vishwa36993272015-11-20 12:43:49 -06001025
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001026 // No response for this command.
vishwa36993272015-11-20 12:43:49 -06001027 *data_len = 0;
1028
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001029 // Catch the actual operaton by peeking into request buffer
Patrick Venture0b02be92018-08-31 11:55:55 -07001030 uint8_t chassis_ctrl_cmd = *(uint8_t*)request;
vishwa36993272015-11-20 12:43:49 -06001031
Patrick Venture0b02be92018-08-31 11:55:55 -07001032 switch (chassis_ctrl_cmd)
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001033 {
1034 case CMD_POWER_ON:
1035 rc = initiate_state_transition(State::Host::Transition::On);
1036 break;
1037 case CMD_POWER_OFF:
Vishwanatha Subbanna8b26d352017-08-04 18:35:18 +05301038 // This path would be hit in 2 conditions.
1039 // 1: When user asks for power off using ipmi chassis command 0x04
1040 // 2: Host asking for power off post shutting down.
1041
1042 // If it's a host requested power off, then need to nudge Softoff
1043 // application that it needs to stop the watchdog timer if running.
1044 // If it is a user requested power off, then this is not really
1045 // needed. But then we need to differentiate between user and host
1046 // calling this same command
1047
1048 // For now, we are going ahead with trying to nudge the soft off and
1049 // interpret the failure to do so as a non softoff case
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001050 rc = stop_soft_off_timer();
Vishwanatha Subbanna8b26d352017-08-04 18:35:18 +05301051
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001052 // Only request the Off transition if the soft power off
1053 // application is not running
1054 if (rc < 0)
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001055 {
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001056 // First create a file to indicate to the soft off application
Vishwanatha Subbanna8b26d352017-08-04 18:35:18 +05301057 // that it should not run. Not doing this will result in State
1058 // manager doing a default soft power off when asked for power
1059 // off.
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001060 indicate_no_softoff_needed();
1061
1062 // Now request the shutdown
1063 rc = initiate_state_transition(State::Host::Transition::Off);
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001064 }
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001065 else
1066 {
Vishwanatha Subbanna8b26d352017-08-04 18:35:18 +05301067 log<level::INFO>("Soft off is running, so let shutdown target "
1068 "stop the host");
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001069 }
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001070 break;
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +05301071
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001072 case CMD_HARD_RESET:
1073 case CMD_POWER_CYCLE:
1074 // SPEC has a section that says certain implementations can trigger
1075 // PowerOn if power is Off when a command to power cycle is
1076 // requested
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001077
1078 // First create a file to indicate to the soft off application
1079 // that it should not run since this is a direct user initiated
1080 // power reboot request (i.e. a reboot request that is not
1081 // originating via a soft power off SMS request)
1082 indicate_no_softoff_needed();
1083
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001084 rc = initiate_state_transition(State::Host::Transition::Reboot);
1085 break;
Vishwanatha Subbanna8b26d352017-08-04 18:35:18 +05301086
1087 case CMD_SOFT_OFF_VIA_OVER_TEMP:
1088 // Request Host State Manager to do a soft power off
1089 rc = initiate_state_transition(State::Host::Transition::Off);
1090 break;
1091
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001092 default:
1093 {
Aditya Saripalli5fb14602017-11-09 14:46:27 +05301094 log<level::ERR>("Invalid Chassis Control command",
1095 entry("CMD=0x%X", chassis_ctrl_cmd));
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001096 rc = -1;
1097 }
1098 }
vishwa36993272015-11-20 12:43:49 -06001099
Patrick Venture0b02be92018-08-31 11:55:55 -07001100 return ((rc < 0) ? IPMI_CC_INVALID : IPMI_CC_OK);
vishwa36993272015-11-20 12:43:49 -06001101}
1102
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001103/** @brief Return D-Bus connection string to enclosure identify LED object
1104 *
1105 * @param[in, out] connection - connection to D-Bus object
1106 * @return a IPMI return code
1107 */
1108std::string getEnclosureIdentifyConnection()
Tom Joseph5110c122018-03-23 17:55:40 +05301109{
Tom Joseph5110c122018-03-23 17:55:40 +05301110 // lookup enclosure_identify group owner(s) in mapper
1111 auto mapperCall = chassis::internal::dbus.new_method_call(
Patrick Venture0b02be92018-08-31 11:55:55 -07001112 ipmi::MAPPER_BUS_NAME, ipmi::MAPPER_OBJ, ipmi::MAPPER_INTF,
1113 "GetObject");
Tom Joseph5110c122018-03-23 17:55:40 +05301114
1115 mapperCall.append(identify_led_object_name);
Patrick Venture0b02be92018-08-31 11:55:55 -07001116 static const std::vector<std::string> interfaces = {
1117 "xyz.openbmc_project.Led.Group"};
Tom Joseph5110c122018-03-23 17:55:40 +05301118 mapperCall.append(interfaces);
1119 auto mapperReply = chassis::internal::dbus.call(mapperCall);
1120 if (mapperReply.is_method_error())
1121 {
1122 log<level::ERR>("Chassis Identify: Error communicating to mapper.");
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001123 elog<InternalFailure>();
Tom Joseph5110c122018-03-23 17:55:40 +05301124 }
1125 std::vector<std::pair<std::string, std::vector<std::string>>> mapperResp;
1126 mapperReply.read(mapperResp);
1127
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001128 if (mapperResp.size() != encIdentifyObjectsSize)
Tom Joseph5110c122018-03-23 17:55:40 +05301129 {
Patrick Venture0b02be92018-08-31 11:55:55 -07001130 log<level::ERR>(
1131 "Invalid number of enclosure identify objects.",
1132 entry("ENC_IDENTITY_OBJECTS_SIZE=%d", mapperResp.size()));
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001133 elog<InternalFailure>();
1134 }
1135 auto pair = mapperResp[encIdentifyObjectsSize - 1];
1136 return pair.first;
1137}
Tom Joseph5110c122018-03-23 17:55:40 +05301138
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001139/** @brief Turn On/Off enclosure identify LED
1140 *
1141 * @param[in] flag - true to turn on LED, false to turn off
1142 * @return a IPMI return code
1143 */
1144void enclosureIdentifyLed(bool flag)
1145{
1146 using namespace chassis::internal;
1147 std::string connection = std::move(getEnclosureIdentifyConnection());
Patrick Venture0b02be92018-08-31 11:55:55 -07001148 auto led =
1149 dbus.new_method_call(connection.c_str(), identify_led_object_name,
1150 "org.freedesktop.DBus.Properties", "Set");
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001151 led.append("xyz.openbmc_project.Led.Group", "Asserted",
Patrick Venture0b02be92018-08-31 11:55:55 -07001152 sdbusplus::message::variant<bool>(flag));
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001153 auto ledReply = dbus.call(led);
1154 if (ledReply.is_method_error())
1155 {
1156 log<level::ERR>("Chassis Identify: Error Setting State On/Off\n",
Patrick Venture0b02be92018-08-31 11:55:55 -07001157 entry("LED_STATE=%d", flag));
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001158 elog<InternalFailure>();
1159 }
1160}
1161
1162/** @brief Callback method to turn off LED
1163 */
1164void enclosureIdentifyLedOff()
1165{
1166 try
1167 {
1168 enclosureIdentifyLed(false);
1169 }
1170 catch (const InternalFailure& e)
1171 {
1172 report<InternalFailure>();
1173 }
1174}
1175
1176/** @brief Create timer to turn on and off the enclosure LED
1177 */
1178void createIdentifyTimer()
1179{
1180 if (!identifyTimer)
1181 {
Vernon Mauery1181af72018-10-08 12:05:00 -07001182 identifyTimer =
1183 std::make_unique<phosphor::Timer>(enclosureIdentifyLedOff);
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001184 }
1185}
1186
1187ipmi_ret_t ipmi_chassis_identify(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1188 ipmi_request_t request,
1189 ipmi_response_t response,
1190 ipmi_data_len_t data_len,
1191 ipmi_context_t context)
1192{
1193 if (*data_len > chassisIdentifyReqLength)
1194 {
1195 return IPMI_CC_REQ_DATA_LEN_INVALID;
1196 }
Patrick Venture0b02be92018-08-31 11:55:55 -07001197 uint8_t identifyInterval =
1198 *data_len > identifyIntervalPos
1199 ? (static_cast<uint8_t*>(request))[identifyIntervalPos]
1200 : DEFAULT_IDENTIFY_TIME_OUT;
1201 bool forceIdentify =
1202 (*data_len == chassisIdentifyReqLength)
1203 ? (static_cast<uint8_t*>(request))[forceIdentifyPos] & 0x01
1204 : false;
Tom Josephbed26992018-07-31 23:00:24 +05301205
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001206 if (identifyInterval || forceIdentify)
1207 {
1208 // stop the timer if already started, for force identify we should
1209 // not turn off LED
Vernon Mauery1181af72018-10-08 12:05:00 -07001210 identifyTimer->stop();
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001211 try
Tom Joseph5110c122018-03-23 17:55:40 +05301212 {
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001213 enclosureIdentifyLed(true);
1214 }
1215 catch (const InternalFailure& e)
1216 {
1217 report<InternalFailure>();
1218 return IPMI_CC_RESPONSE_ERROR;
Tom Joseph5110c122018-03-23 17:55:40 +05301219 }
1220
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001221 if (forceIdentify)
Tom Joseph5110c122018-03-23 17:55:40 +05301222 {
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001223 return IPMI_CC_OK;
1224 }
1225 // start the timer
1226 auto time = std::chrono::duration_cast<std::chrono::microseconds>(
Patrick Venture0b02be92018-08-31 11:55:55 -07001227 std::chrono::seconds(identifyInterval));
Vernon Mauery1181af72018-10-08 12:05:00 -07001228 identifyTimer->start(time);
Tom Joseph5110c122018-03-23 17:55:40 +05301229 }
Tom Josephbed26992018-07-31 23:00:24 +05301230 else if (!identifyInterval)
1231 {
Vernon Mauery1181af72018-10-08 12:05:00 -07001232 identifyTimer->stop();
Tom Josephbed26992018-07-31 23:00:24 +05301233 enclosureIdentifyLedOff();
1234 }
Tom Joseph5110c122018-03-23 17:55:40 +05301235 return IPMI_CC_OK;
1236}
1237
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001238namespace boot_options
1239{
1240
1241using namespace sdbusplus::xyz::openbmc_project::Control::Boot::server;
1242using IpmiValue = uint8_t;
1243constexpr auto ipmiDefault = 0;
1244
Patrick Venture0b02be92018-08-31 11:55:55 -07001245std::map<IpmiValue, Source::Sources> sourceIpmiToDbus = {
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001246 {0x01, Source::Sources::Network},
1247 {0x02, Source::Sources::Disk},
1248 {0x05, Source::Sources::ExternalMedia},
Patrick Venture0b02be92018-08-31 11:55:55 -07001249 {ipmiDefault, Source::Sources::Default}};
shgoupfd84fbbf2015-12-17 10:05:51 +08001250
Patrick Venture0b02be92018-08-31 11:55:55 -07001251std::map<IpmiValue, Mode::Modes> modeIpmiToDbus = {
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001252 {0x03, Mode::Modes::Safe},
1253 {0x06, Mode::Modes::Setup},
Patrick Venture0b02be92018-08-31 11:55:55 -07001254 {ipmiDefault, Mode::Modes::Regular}};
shgoupfd84fbbf2015-12-17 10:05:51 +08001255
Patrick Venture0b02be92018-08-31 11:55:55 -07001256std::map<Source::Sources, IpmiValue> sourceDbusToIpmi = {
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001257 {Source::Sources::Network, 0x01},
1258 {Source::Sources::Disk, 0x02},
1259 {Source::Sources::ExternalMedia, 0x05},
Patrick Venture0b02be92018-08-31 11:55:55 -07001260 {Source::Sources::Default, ipmiDefault}};
shgoupfd84fbbf2015-12-17 10:05:51 +08001261
Patrick Venture0b02be92018-08-31 11:55:55 -07001262std::map<Mode::Modes, IpmiValue> modeDbusToIpmi = {
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001263 {Mode::Modes::Safe, 0x03},
1264 {Mode::Modes::Setup, 0x06},
Patrick Venture0b02be92018-08-31 11:55:55 -07001265 {Mode::Modes::Regular, ipmiDefault}};
shgoupfd84fbbf2015-12-17 10:05:51 +08001266
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001267} // namespace boot_options
shgoupfd84fbbf2015-12-17 10:05:51 +08001268
Marri Devender Rao81719702018-05-07 00:53:48 -05001269/** @brief Set the property value for boot source
1270 * @param[in] source - boot source value
1271 * @return On failure return IPMI error.
1272 */
1273static ipmi_ret_t setBootSource(const Source::Sources& source)
1274{
1275 using namespace chassis::internal;
1276 using namespace chassis::internal::cache;
1277 sdbusplus::message::variant<std::string> property =
1278 convertForMessage(source);
1279 auto bootSetting = settings::boot::setting(objects, bootSourceIntf);
1280 const auto& bootSourceSetting = std::get<settings::Path>(bootSetting);
Patrick Venture0b02be92018-08-31 11:55:55 -07001281 auto method = dbus.new_method_call(
1282 objects.service(bootSourceSetting, bootSourceIntf).c_str(),
1283 bootSourceSetting.c_str(), ipmi::PROP_INTF, "Set");
Marri Devender Rao81719702018-05-07 00:53:48 -05001284 method.append(bootSourceIntf, "BootSource", property);
1285 auto reply = dbus.call(method);
1286 if (reply.is_method_error())
1287 {
1288 log<level::ERR>("Error in BootSource Set");
1289 report<InternalFailure>();
1290 return IPMI_CC_UNSPECIFIED_ERROR;
1291 }
1292 return IPMI_CC_OK;
1293}
1294
Patrick Venture0b02be92018-08-31 11:55:55 -07001295/** @brief Set the property value for boot mode
Marri Devender Rao81719702018-05-07 00:53:48 -05001296 * @param[in] mode - boot mode value
1297 * @return On failure return IPMI error.
1298 */
1299static ipmi_ret_t setBootMode(const Mode::Modes& mode)
1300{
1301 using namespace chassis::internal;
1302 using namespace chassis::internal::cache;
Patrick Venture0b02be92018-08-31 11:55:55 -07001303 sdbusplus::message::variant<std::string> property = convertForMessage(mode);
Marri Devender Rao81719702018-05-07 00:53:48 -05001304 auto bootSetting = settings::boot::setting(objects, bootModeIntf);
1305 const auto& bootModeSetting = std::get<settings::Path>(bootSetting);
Patrick Venture0b02be92018-08-31 11:55:55 -07001306 auto method = dbus.new_method_call(
1307 objects.service(bootModeSetting, bootModeIntf).c_str(),
1308 bootModeSetting.c_str(), ipmi::PROP_INTF, "Set");
Marri Devender Rao81719702018-05-07 00:53:48 -05001309 method.append(bootModeIntf, "BootMode", property);
1310 auto reply = dbus.call(method);
1311 if (reply.is_method_error())
1312 {
1313 log<level::ERR>("Error in BootMode Set");
1314 report<InternalFailure>();
1315 return IPMI_CC_UNSPECIFIED_ERROR;
1316 }
1317 return IPMI_CC_OK;
1318}
1319
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001320ipmi_ret_t ipmi_chassis_get_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1321 ipmi_request_t request,
1322 ipmi_response_t response,
1323 ipmi_data_len_t data_len,
1324 ipmi_context_t context)
Adriana Kobylak40814c62015-10-27 15:58:44 -05001325{
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_PARM_NOT_SUPPORTED;
Patrick Venture0b02be92018-08-31 11:55:55 -07001328 char* p = NULL;
1329 get_sys_boot_options_response_t* resp =
1330 (get_sys_boot_options_response_t*)response;
1331 get_sys_boot_options_t* reqptr = (get_sys_boot_options_t*)request;
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001332 IpmiValue bootOption = ipmiDefault;
Adriana Kobylak40814c62015-10-27 15:58:44 -05001333
Patrick Ventureb51bf9c2018-09-10 15:53:14 -07001334 std::memset(resp, 0, sizeof(*resp));
Patrick Venture0b02be92018-08-31 11:55:55 -07001335 resp->version = SET_PARM_VERSION;
1336 resp->parm = 5;
1337 resp->data[0] = SET_PARM_BOOT_FLAGS_VALID_ONE_TIME;
Adriana Kobylak40814c62015-10-27 15:58:44 -05001338
shgoupfd84fbbf2015-12-17 10:05:51 +08001339 /*
1340 * Parameter #5 means boot flags. Please refer to 28.13 of ipmi doc.
1341 * This is the only parameter used by petitboot.
1342 */
Patrick Venture0b02be92018-08-31 11:55:55 -07001343 if (reqptr->parameter ==
1344 static_cast<uint8_t>(BootOptionParameter::BOOT_FLAGS))
1345 {
shgoupfd84fbbf2015-12-17 10:05:51 +08001346
Ratan Guptafd28dd72016-08-01 04:58:01 -05001347 *data_len = static_cast<uint8_t>(BootOptionResponseSize::BOOT_FLAGS);
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001348 using namespace chassis::internal;
1349 using namespace chassis::internal::cache;
shgoupfd84fbbf2015-12-17 10:05:51 +08001350
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001351 try
ratagupta6f6bff2016-04-04 06:20:11 -05001352 {
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001353 auto bootSetting = settings::boot::setting(objects, bootSourceIntf);
1354 const auto& bootSourceSetting =
1355 std::get<settings::Path>(bootSetting);
1356 auto oneTimeEnabled =
1357 std::get<settings::boot::OneTimeEnabled>(bootSetting);
Patrick Venture0b02be92018-08-31 11:55:55 -07001358 auto method = dbus.new_method_call(
1359 objects.service(bootSourceSetting, bootSourceIntf).c_str(),
1360 bootSourceSetting.c_str(), ipmi::PROP_INTF, "Get");
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001361 method.append(bootSourceIntf, "BootSource");
1362 auto reply = dbus.call(method);
1363 if (reply.is_method_error())
1364 {
1365 log<level::ERR>("Error in BootSource Get");
1366 report<InternalFailure>();
1367 *data_len = 0;
1368 return IPMI_CC_UNSPECIFIED_ERROR;
1369 }
1370 sdbusplus::message::variant<std::string> result;
1371 reply.read(result);
William A. Kennington III4c008022018-10-12 17:18:14 -07001372 auto bootSource = Source::convertSourcesFromString(
1373 variant_ns::get<std::string>(result));
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001374
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001375 bootSetting = settings::boot::setting(objects, bootModeIntf);
1376 const auto& bootModeSetting = std::get<settings::Path>(bootSetting);
1377 method = dbus.new_method_call(
Patrick Venture0b02be92018-08-31 11:55:55 -07001378 objects.service(bootModeSetting, bootModeIntf).c_str(),
1379 bootModeSetting.c_str(), ipmi::PROP_INTF, "Get");
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001380 method.append(bootModeIntf, "BootMode");
1381 reply = dbus.call(method);
1382 if (reply.is_method_error())
1383 {
1384 log<level::ERR>("Error in BootMode Get");
1385 report<InternalFailure>();
1386 *data_len = 0;
1387 return IPMI_CC_UNSPECIFIED_ERROR;
1388 }
1389 reply.read(result);
William A. Kennington III4c008022018-10-12 17:18:14 -07001390 auto bootMode = Mode::convertModesFromString(
1391 variant_ns::get<std::string>(result));
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001392
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001393 bootOption = sourceDbusToIpmi.at(bootSource);
1394 if ((Mode::Modes::Regular == bootMode) &&
1395 (Source::Sources::Default == bootSource))
1396 {
1397 bootOption = ipmiDefault;
1398 }
1399 else if (Source::Sources::Default == bootSource)
1400 {
1401 bootOption = modeDbusToIpmi.at(bootMode);
1402 }
1403 resp->data[1] = (bootOption << 2);
ratagupta6f6bff2016-04-04 06:20:11 -05001404
Patrick Venture0b02be92018-08-31 11:55:55 -07001405 resp->data[0] = oneTimeEnabled
1406 ? SET_PARM_BOOT_FLAGS_VALID_ONE_TIME
1407 : SET_PARM_BOOT_FLAGS_VALID_PERMANENT;
ratagupta6f6bff2016-04-04 06:20:11 -05001408
ratagupta6f6bff2016-04-04 06:20:11 -05001409 rc = IPMI_CC_OK;
ratagupta6f6bff2016-04-04 06:20:11 -05001410 }
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001411 catch (InternalFailure& e)
1412 {
1413 report<InternalFailure>();
1414 *data_len = 0;
1415 return IPMI_CC_UNSPECIFIED_ERROR;
1416 }
Patrick Venture0b02be92018-08-31 11:55:55 -07001417 }
1418 else if (reqptr->parameter ==
1419 static_cast<uint8_t>(BootOptionParameter::OPAL_NETWORK_SETTINGS))
1420 {
Ratan Guptafd28dd72016-08-01 04:58:01 -05001421
Patrick Venture0b02be92018-08-31 11:55:55 -07001422 *data_len =
1423 static_cast<uint8_t>(BootOptionResponseSize::OPAL_NETWORK_SETTINGS);
Ratan Guptafd28dd72016-08-01 04:58:01 -05001424
Patrick Venture0b02be92018-08-31 11:55:55 -07001425 resp->parm =
1426 static_cast<uint8_t>(BootOptionParameter::OPAL_NETWORK_SETTINGS);
Ratan Guptafd28dd72016-08-01 04:58:01 -05001427
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001428 int ret = getHostNetworkData(resp);
Ratan Guptafd28dd72016-08-01 04:58:01 -05001429
Patrick Venture0b02be92018-08-31 11:55:55 -07001430 if (ret < 0)
1431 {
Ratan Guptafd28dd72016-08-01 04:58:01 -05001432
Aditya Saripalli5fb14602017-11-09 14:46:27 +05301433 log<level::ERR>(
Patrick Venture0b02be92018-08-31 11:55:55 -07001434 "getHostNetworkData failed for get_sys_boot_options.");
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001435 rc = IPMI_CC_UNSPECIFIED_ERROR;
Patrick Venture0b02be92018-08-31 11:55:55 -07001436 }
1437 else
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001438 rc = IPMI_CC_OK;
Ratan Guptafd28dd72016-08-01 04:58:01 -05001439 }
1440
Patrick Venture0b02be92018-08-31 11:55:55 -07001441 else
1442 {
1443 log<level::ERR>("Unsupported parameter",
1444 entry("PARAM=0x%x", reqptr->parameter));
shgoupfd84fbbf2015-12-17 10:05:51 +08001445 }
1446
1447 if (p)
1448 free(p);
1449
Ratan Guptafd28dd72016-08-01 04:58:01 -05001450 if (rc == IPMI_CC_OK)
1451 {
1452 *data_len += 2;
1453 }
1454
shgoupfd84fbbf2015-12-17 10:05:51 +08001455 return rc;
1456}
1457
shgoupfd84fbbf2015-12-17 10:05:51 +08001458ipmi_ret_t ipmi_chassis_set_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001459 ipmi_request_t request,
1460 ipmi_response_t response,
1461 ipmi_data_len_t data_len,
1462 ipmi_context_t context)
shgoupfd84fbbf2015-12-17 10:05:51 +08001463{
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001464 using namespace boot_options;
shgoupfd84fbbf2015-12-17 10:05:51 +08001465 ipmi_ret_t rc = IPMI_CC_OK;
Patrick Venture0b02be92018-08-31 11:55:55 -07001466 set_sys_boot_options_t* reqptr = (set_sys_boot_options_t*)request;
shgoupfd84fbbf2015-12-17 10:05:51 +08001467
Patrick Ventureb51bf9c2018-09-10 15:53:14 -07001468 std::printf("IPMI SET_SYS_BOOT_OPTIONS reqptr->parameter =[%d]\n",
1469 reqptr->parameter);
Ratan Guptafd28dd72016-08-01 04:58:01 -05001470
shgoupfd84fbbf2015-12-17 10:05:51 +08001471 // This IPMI command does not have any resposne data
1472 *data_len = 0;
1473
1474 /* 000101
1475 * Parameter #5 means boot flags. Please refer to 28.13 of ipmi doc.
1476 * This is the only parameter used by petitboot.
1477 */
Ratan Guptafd28dd72016-08-01 04:58:01 -05001478
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001479 if (reqptr->parameter == (uint8_t)BootOptionParameter::BOOT_FLAGS)
1480 {
1481 IpmiValue bootOption = ((reqptr->data[1] & 0x3C) >> 2);
1482 using namespace chassis::internal;
1483 using namespace chassis::internal::cache;
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001484 auto oneTimeEnabled = false;
1485 constexpr auto enabledIntf = "xyz.openbmc_project.Object.Enable";
Tom Joseph57e8eb72017-09-25 18:05:02 +05301486 constexpr auto oneTimePath =
Patrick Venture0b02be92018-08-31 11:55:55 -07001487 "/xyz/openbmc_project/control/host0/boot/one_time";
shgoupfd84fbbf2015-12-17 10:05:51 +08001488
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001489 try
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001490 {
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001491 bool permanent =
1492 (reqptr->data[0] & SET_PARM_BOOT_FLAGS_PERMANENT) ==
1493 SET_PARM_BOOT_FLAGS_PERMANENT;
1494
Patrick Venture0b02be92018-08-31 11:55:55 -07001495 auto bootSetting = settings::boot::setting(objects, bootSourceIntf);
Tom Joseph57e8eb72017-09-25 18:05:02 +05301496
1497 oneTimeEnabled =
1498 std::get<settings::boot::OneTimeEnabled>(bootSetting);
1499
1500 /*
1501 * Check if the current boot setting is onetime or permanent, if the
1502 * request in the command is otherwise, then set the "Enabled"
1503 * property in one_time object path to 'True' to indicate onetime
1504 * and 'False' to indicate permanent.
1505 *
1506 * Once the onetime/permanent setting is applied, then the bootMode
1507 * and bootSource is updated for the corresponding object.
1508 */
1509 if ((permanent && oneTimeEnabled) ||
1510 (!permanent && !oneTimeEnabled))
1511 {
1512 auto service = ipmi::getService(dbus, enabledIntf, oneTimePath);
1513
Patrick Venture0b02be92018-08-31 11:55:55 -07001514 ipmi::setDbusProperty(dbus, service, oneTimePath, enabledIntf,
1515 "Enabled", !permanent);
Tom Joseph57e8eb72017-09-25 18:05:02 +05301516 }
1517
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001518 auto modeItr = modeIpmiToDbus.find(bootOption);
1519 auto sourceItr = sourceIpmiToDbus.find(bootOption);
1520 if (sourceIpmiToDbus.end() != sourceItr)
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001521 {
Marri Devender Rao81719702018-05-07 00:53:48 -05001522 rc = setBootSource(sourceItr->second);
1523 if (rc != IPMI_CC_OK)
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001524 {
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001525 *data_len = 0;
Marri Devender Rao81719702018-05-07 00:53:48 -05001526 return rc;
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001527 }
Marri Devender Rao54fa1302018-05-07 01:06:23 -05001528 // If a set boot device is mapping to a boot source, then reset
1529 // the boot mode D-Bus property to default.
1530 // This way the ipmid code can determine which property is not
1531 // at the default value
Patrick Venture0b02be92018-08-31 11:55:55 -07001532 if (sourceItr->second != Source::Sources::Default)
Marri Devender Rao54fa1302018-05-07 01:06:23 -05001533 {
1534 setBootMode(Mode::Modes::Regular);
1535 }
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001536 }
1537 if (modeIpmiToDbus.end() != modeItr)
1538 {
Marri Devender Rao81719702018-05-07 00:53:48 -05001539 rc = setBootMode(modeItr->second);
1540 if (rc != IPMI_CC_OK)
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001541 {
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001542 *data_len = 0;
Marri Devender Rao81719702018-05-07 00:53:48 -05001543 return rc;
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001544 }
Marri Devender Rao54fa1302018-05-07 01:06:23 -05001545 // If a set boot device is mapping to a boot mode, then reset
1546 // the boot source D-Bus property to default.
1547 // This way the ipmid code can determine which property is not
1548 // at the default value
Patrick Venture0b02be92018-08-31 11:55:55 -07001549 if (modeItr->second != Mode::Modes::Regular)
Marri Devender Rao54fa1302018-05-07 01:06:23 -05001550 {
1551 setBootSource(Source::Sources::Default);
1552 }
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001553 }
1554 }
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001555 catch (InternalFailure& e)
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001556 {
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001557 report<InternalFailure>();
1558 *data_len = 0;
1559 return IPMI_CC_UNSPECIFIED_ERROR;
shgoupfd84fbbf2015-12-17 10:05:51 +08001560 }
Patrick Venture0b02be92018-08-31 11:55:55 -07001561 }
1562 else if (reqptr->parameter ==
1563 (uint8_t)BootOptionParameter::OPAL_NETWORK_SETTINGS)
1564 {
Ratan Guptafd28dd72016-08-01 04:58:01 -05001565
1566 int ret = setHostNetworkData(reqptr);
Patrick Venture0b02be92018-08-31 11:55:55 -07001567 if (ret < 0)
1568 {
Aditya Saripalli5fb14602017-11-09 14:46:27 +05301569 log<level::ERR>(
Patrick Venture0b02be92018-08-31 11:55:55 -07001570 "setHostNetworkData failed for set_sys_boot_options");
Ratan Guptafd28dd72016-08-01 04:58:01 -05001571 rc = IPMI_CC_UNSPECIFIED_ERROR;
1572 }
Patrick Venture0b02be92018-08-31 11:55:55 -07001573 }
1574 else if (reqptr->parameter ==
1575 static_cast<uint8_t>(BootOptionParameter::BOOT_INFO))
1576 {
Tom Josephf536c902017-09-25 18:08:15 +05301577 // Handle parameter #4 and return command completed normally
1578 // (IPMI_CC_OK). There is no implementation in OpenBMC for this
1579 // parameter. This is added to support the ipmitool command `chassis
1580 // bootdev` which sends set on parameter #4, before setting the boot
1581 // flags.
1582 rc = IPMI_CC_OK;
Patrick Venture0b02be92018-08-31 11:55:55 -07001583 }
1584 else
1585 {
1586 log<level::ERR>("Unsupported parameter",
1587 entry("PARAM=0x%x", reqptr->parameter));
shgoupfd84fbbf2015-12-17 10:05:51 +08001588 rc = IPMI_CC_PARM_NOT_SUPPORTED;
Adriana Kobylak40814c62015-10-27 15:58:44 -05001589 }
1590
1591 return rc;
1592}
1593
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -05001594ipmi_ret_t ipmiGetPOHCounter(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1595 ipmi_request_t request, ipmi_response_t response,
1596 ipmi_data_len_t data_len, ipmi_context_t context)
1597{
1598 // sd_bus error
1599 ipmi_ret_t rc = IPMI_CC_OK;
1600
1601 auto resptr = reinterpret_cast<GetPOHCountResponse*>(response);
1602
1603 try
1604 {
1605 auto pohCounter = getPOHCounter();
1606 resptr->counterReading[0] = pohCounter;
1607 resptr->counterReading[1] = pohCounter >> 8;
1608 resptr->counterReading[2] = pohCounter >> 16;
1609 resptr->counterReading[3] = pohCounter >> 24;
1610 }
1611 catch (std::exception& e)
1612 {
1613 log<level::ERR>(e.what());
1614 return IPMI_CC_UNSPECIFIED_ERROR;
1615 }
1616
1617 resptr->minPerCount = poh::minutesPerCount;
1618 *data_len = sizeof(GetPOHCountResponse);
1619
1620 return rc;
1621}
1622
Yong Lic6713cf2018-09-12 12:35:13 +08001623ipmi_ret_t ipmi_chassis_set_power_restore_policy(
1624 ipmi_netfn_t netfn, ipmi_cmd_t cmd, ipmi_request_t request,
1625 ipmi_response_t response, ipmi_data_len_t data_len, ipmi_context_t context)
1626{
1627 auto* reqptr = reinterpret_cast<uint8_t*>(request);
1628 auto* resptr = reinterpret_cast<uint8_t*>(response);
1629 uint8_t reqPolicy = 0;
1630
1631 power_policy::DbusValue value =
1632 power_policy::RestorePolicy::Policy::AlwaysOff;
1633
1634 if (*data_len != power_policy::setPolicyReqLen)
1635 {
1636 phosphor::logging::log<level::ERR>("Unsupported request length",
1637 entry("LEN=0x%x", *data_len));
1638 *data_len = 0;
1639 return IPMI_CC_REQ_DATA_LEN_INVALID;
1640 }
1641
1642 reqPolicy = *reqptr & power_policy::policyBitMask;
1643 if (reqPolicy > power_policy::noChange)
1644 {
1645 phosphor::logging::log<level::ERR>("Reserved request parameter",
1646 entry("REQ=0x%x", reqPolicy));
1647 *data_len = 0;
1648 return IPMI_CC_PARM_NOT_SUPPORTED;
1649 }
1650
1651 if (reqPolicy == power_policy::noChange)
1652 {
1653 // just return the supported policy
1654 *resptr = power_policy::allSupport;
1655 *data_len = power_policy::setPolicyReqLen;
1656 return IPMI_CC_OK;
1657 }
1658
1659 for (auto const& it : power_policy::dbusToIpmi)
1660 {
1661 if (it.second == reqPolicy)
1662 {
1663 value = it.first;
1664 break;
1665 }
1666 }
1667
1668 try
1669 {
1670 const settings::Path& powerRestoreSetting =
1671 chassis::internal::cache::objects.map
1672 .at(chassis::internal::powerRestoreIntf)
1673 .front();
1674 sdbusplus::message::variant<std::string> property =
1675 convertForMessage(value);
1676
1677 auto method = chassis::internal::dbus.new_method_call(
1678 chassis::internal::cache::objects
1679 .service(powerRestoreSetting,
1680 chassis::internal::powerRestoreIntf)
1681 .c_str(),
1682 powerRestoreSetting.c_str(), ipmi::PROP_INTF, "Set");
1683
1684 method.append(chassis::internal::powerRestoreIntf, "PowerRestorePolicy",
1685 property);
1686 auto reply = chassis::internal::dbus.call(method);
1687 if (reply.is_method_error())
1688 {
1689 phosphor::logging::log<level::ERR>("Unspecified Error");
1690 *data_len = 0;
1691 return IPMI_CC_UNSPECIFIED_ERROR;
1692 }
1693 }
1694 catch (InternalFailure& e)
1695 {
1696 report<InternalFailure>();
1697 *data_len = 0;
1698 return IPMI_CC_UNSPECIFIED_ERROR;
1699 }
1700
1701 *data_len = power_policy::setPolicyReqLen;
1702 return IPMI_CC_OK;
1703}
1704
Adriana Kobylak40814c62015-10-27 15:58:44 -05001705void register_netfn_chassis_functions()
1706{
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001707 createIdentifyTimer();
1708
Tom05732372016-09-06 17:21:23 +05301709 // <Wildcard Command>
Patrick Venture0b02be92018-08-31 11:55:55 -07001710 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_WILDCARD, NULL,
1711 ipmi_chassis_wildcard, PRIVILEGE_USER);
Adriana Kobylak40814c62015-10-27 15:58:44 -05001712
Tom05732372016-09-06 17:21:23 +05301713 // Get Chassis Capabilities
Patrick Venture0b02be92018-08-31 11:55:55 -07001714 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_GET_CHASSIS_CAP, NULL,
1715 ipmi_get_chassis_cap, PRIVILEGE_USER);
Nan Li8d15fb42016-08-16 22:29:40 +08001716
Tom05732372016-09-06 17:21:23 +05301717 // <Get System Boot Options>
Tom05732372016-09-06 17:21:23 +05301718 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_GET_SYS_BOOT_OPTIONS, NULL,
Patrick Venture0b02be92018-08-31 11:55:55 -07001719 ipmi_chassis_get_sys_boot_options,
1720 PRIVILEGE_OPERATOR);
Adriana Kobylak40814c62015-10-27 15:58:44 -05001721
Tom05732372016-09-06 17:21:23 +05301722 // <Get Chassis Status>
Patrick Venture0b02be92018-08-31 11:55:55 -07001723 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_CHASSIS_STATUS, NULL,
1724 ipmi_get_chassis_status, PRIVILEGE_USER);
Nan Lifdd8ec52016-08-28 03:57:40 +08001725
Tom05732372016-09-06 17:21:23 +05301726 // <Chassis Control>
Patrick Venture0b02be92018-08-31 11:55:55 -07001727 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_CHASSIS_CONTROL, NULL,
1728 ipmi_chassis_control, PRIVILEGE_OPERATOR);
shgoupfd84fbbf2015-12-17 10:05:51 +08001729
Tom Joseph5110c122018-03-23 17:55:40 +05301730 // <Chassis Identify>
Tom Joseph5110c122018-03-23 17:55:40 +05301731 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_CHASSIS_IDENTIFY, NULL,
1732 ipmi_chassis_identify, PRIVILEGE_OPERATOR);
1733
Tom05732372016-09-06 17:21:23 +05301734 // <Set System Boot Options>
Tom05732372016-09-06 17:21:23 +05301735 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_SET_SYS_BOOT_OPTIONS, NULL,
Patrick Venture0b02be92018-08-31 11:55:55 -07001736 ipmi_chassis_set_sys_boot_options,
1737 PRIVILEGE_OPERATOR);
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -05001738 // <Get POH Counter>
1739 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_GET_POH_COUNTER, NULL,
1740 ipmiGetPOHCounter, PRIVILEGE_USER);
Yong Lic6713cf2018-09-12 12:35:13 +08001741
1742 // <Set Power Restore Policy>
1743 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_SET_RESTORE_POLICY, NULL,
1744 ipmi_chassis_set_power_restore_policy,
1745 PRIVILEGE_OPERATOR);
vishwa36993272015-11-20 12:43:49 -06001746}