blob: 4b42b3ca84711d2f0fa65b0dfee0028267fc0528 [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";
Patrick Venture0b02be92018-08-31 11:55:55 -070091const char* identify_led_object_name =
Tom Joseph5110c122018-03-23 17:55:40 +053092 "/xyz/openbmc_project/led/groups/enclosure_identify";
shgoupfd84fbbf2015-12-17 10:05:51 +080093
Ratan Guptadcb10672017-07-10 10:33:50 +053094constexpr auto SETTINGS_ROOT = "/";
95constexpr auto SETTINGS_MATCH = "host0";
Ratan Guptadcb10672017-07-10 10:33:50 +053096
97constexpr auto IP_INTERFACE = "xyz.openbmc_project.Network.IP";
98constexpr auto MAC_INTERFACE = "xyz.openbmc_project.Network.MACAddress";
99
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -0500100static constexpr auto chassisStateRoot = "/xyz/openbmc_project/state";
101static constexpr auto chassisPOHStateIntf =
Patrick Venture0b02be92018-08-31 11:55:55 -0700102 "xyz.openbmc_project.State.PowerOnHours";
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -0500103static constexpr auto pOHCounterProperty = "POHCounter";
104static constexpr auto match = "chassis0";
Yong Liae4b0402018-11-02 11:12:14 +0800105const static constexpr char chassisCapIntf[] =
106 "xyz.openbmc_project.Control.ChassisCapabilities";
107const static constexpr char chassisCapFlagsProp[] = "CapabilitiesFlags";
108const static constexpr char chassisFRUDevAddrProp[] = "FRUDeviceAddress";
109const static constexpr char chassisSDRDevAddrProp[] = "SDRDeviceAddress";
110const static constexpr char chassisSELDevAddrProp[] = "SELDeviceAddress";
111const static constexpr char chassisSMDevAddrProp[] = "SMDeviceAddress";
112const static constexpr char chassisBridgeDevAddrProp[] = "BridgeDeviceAddress";
113static constexpr uint8_t chassisCapFlagMask = 0x0f;
114static constexpr uint8_t chassisCapAddrMask = 0xfe;
Ratan Guptadcb10672017-07-10 10:33:50 +0530115
Nan Li8d15fb42016-08-16 22:29:40 +0800116typedef struct
117{
118 uint8_t cap_flags;
119 uint8_t fru_info_dev_addr;
120 uint8_t sdr_dev_addr;
121 uint8_t sel_dev_addr;
122 uint8_t system_management_dev_addr;
123 uint8_t bridge_dev_addr;
Patrick Venture0b02be92018-08-31 11:55:55 -0700124} __attribute__((packed)) ipmi_chassis_cap_t;
Nan Li8d15fb42016-08-16 22:29:40 +0800125
Nan Lifdd8ec52016-08-28 03:57:40 +0800126typedef struct
127{
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500128 uint8_t cur_power_state;
129 uint8_t last_power_event;
130 uint8_t misc_power_state;
131 uint8_t front_panel_button_cap_status;
Patrick Venture0b02be92018-08-31 11:55:55 -0700132} __attribute__((packed)) ipmi_get_chassis_status_t;
Nan Lifdd8ec52016-08-28 03:57:40 +0800133
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -0500134/**
135 * @struct Get POH counter command response data
136 */
137struct GetPOHCountResponse
138{
Patrick Venture0b02be92018-08-31 11:55:55 -0700139 uint8_t minPerCount; ///< Minutes per count
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -0500140 uint8_t counterReading[4]; ///< Counter reading
Patrick Venture0b02be92018-08-31 11:55:55 -0700141} __attribute__((packed));
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -0500142
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530143// Phosphor Host State manager
144namespace State = sdbusplus::xyz::openbmc_project::State::server;
145
Vernon Mauery185b9f82018-07-20 10:52:36 -0700146namespace fs = std::filesystem;
Andrew Geisslera6e3a302017-05-31 19:34:00 -0500147
Ratan Guptadcb10672017-07-10 10:33:50 +0530148using namespace phosphor::logging;
149using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Marri Devender Rao81719702018-05-07 00:53:48 -0500150using namespace sdbusplus::xyz::openbmc_project::Control::Boot::server;
William A. Kennington III4c008022018-10-12 17:18:14 -0700151namespace variant_ns = sdbusplus::message::variant_ns;
152
Deepak Kodihalli8cc19362017-07-21 11:18:38 -0500153namespace chassis
154{
155namespace internal
156{
157
158constexpr auto bootModeIntf = "xyz.openbmc_project.Control.Boot.Mode";
159constexpr auto bootSourceIntf = "xyz.openbmc_project.Control.Boot.Source";
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500160constexpr auto powerRestoreIntf =
161 "xyz.openbmc_project.Control.Power.RestorePolicy";
Deepak Kodihalli8cc19362017-07-21 11:18:38 -0500162sdbusplus::bus::bus dbus(ipmid_get_sd_bus_connection());
163
164namespace cache
165{
166
167settings::Objects objects(dbus,
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500168 {bootModeIntf, bootSourceIntf, powerRestoreIntf});
Deepak Kodihalli8cc19362017-07-21 11:18:38 -0500169
170} // namespace cache
171} // namespace internal
172} // namespace chassis
173
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -0500174namespace poh
175{
176
177constexpr auto minutesPerCount = 60;
178
179} // namespace poh
180
Patrick Venture0b02be92018-08-31 11:55:55 -0700181struct get_sys_boot_options_t
182{
Adriana Kobylak40814c62015-10-27 15:58:44 -0500183 uint8_t parameter;
184 uint8_t set;
185 uint8_t block;
Patrick Venture0b02be92018-08-31 11:55:55 -0700186} __attribute__((packed));
Adriana Kobylak40814c62015-10-27 15:58:44 -0500187
Patrick Venture0b02be92018-08-31 11:55:55 -0700188struct get_sys_boot_options_response_t
189{
shgoupfd84fbbf2015-12-17 10:05:51 +0800190 uint8_t version;
191 uint8_t parm;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500192 uint8_t data[SIZE_BOOT_OPTION];
Patrick Venture0b02be92018-08-31 11:55:55 -0700193} __attribute__((packed));
shgoupfd84fbbf2015-12-17 10:05:51 +0800194
Patrick Venture0b02be92018-08-31 11:55:55 -0700195struct set_sys_boot_options_t
196{
shgoupfd84fbbf2015-12-17 10:05:51 +0800197 uint8_t parameter;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500198 uint8_t data[SIZE_BOOT_OPTION];
Patrick Venture0b02be92018-08-31 11:55:55 -0700199} __attribute__((packed));
Ratan Guptafd28dd72016-08-01 04:58:01 -0500200
Ratan Guptadcb10672017-07-10 10:33:50 +0530201int getHostNetworkData(get_sys_boot_options_response_t* respptr)
Ratan Guptafd28dd72016-08-01 04:58:01 -0500202{
Ratan Guptadcb10672017-07-10 10:33:50 +0530203 ipmi::PropertyMap properties;
204 int rc = 0;
Ratan Gupta8c31d232017-08-13 05:49:43 +0530205 uint8_t addrSize = ipmi::network::IPV4_ADDRESS_SIZE_BYTE;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500206
Ratan Guptadcb10672017-07-10 10:33:50 +0530207 try
208 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700209 // TODO There may be cases where an interface is implemented by multiple
Ratan Guptadcb10672017-07-10 10:33:50 +0530210 // objects,to handle such cases we are interested on that object
211 // which are on interested busname.
212 // Currenlty mapper doesn't give the readable busname(gives busid)
213 // so we can't match with bus name so giving some object specific info
214 // as SETTINGS_MATCH.
215 // Later SETTINGS_MATCH will be replaced with busname.
Ratan Guptafd28dd72016-08-01 04:58:01 -0500216
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530217 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
Ratan Guptadcb10672017-07-10 10:33:50 +0530218
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530219 auto ipObjectInfo = ipmi::getDbusObject(bus, IP_INTERFACE,
220 SETTINGS_ROOT, SETTINGS_MATCH);
221
222 auto macObjectInfo = ipmi::getDbusObject(bus, MAC_INTERFACE,
223 SETTINGS_ROOT, SETTINGS_MATCH);
224
Patrick Venture0b02be92018-08-31 11:55:55 -0700225 properties = ipmi::getAllDbusProperties(
226 bus, ipObjectInfo.second, ipObjectInfo.first, IP_INTERFACE);
227 auto variant = ipmi::getDbusProperty(bus, macObjectInfo.second,
228 macObjectInfo.first, MAC_INTERFACE,
229 "MACAddress");
Ratan Guptadcb10672017-07-10 10:33:50 +0530230
William A. Kennington III4c008022018-10-12 17:18:14 -0700231 auto ipAddress = variant_ns::get<std::string>(properties["Address"]);
Ratan Guptad70f4532017-08-04 02:07:31 +0530232
William A. Kennington III4c008022018-10-12 17:18:14 -0700233 auto gateway = variant_ns::get<std::string>(properties["Gateway"]);
Ratan Guptad70f4532017-08-04 02:07:31 +0530234
William A. Kennington III4c008022018-10-12 17:18:14 -0700235 auto prefix = variant_ns::get<uint8_t>(properties["PrefixLength"]);
Ratan Guptad70f4532017-08-04 02:07:31 +0530236
Patrick Venture0b02be92018-08-31 11:55:55 -0700237 uint8_t isStatic =
William A. Kennington III4c008022018-10-12 17:18:14 -0700238 (variant_ns::get<std::string>(properties["Origin"]) ==
Patrick Venture0b02be92018-08-31 11:55:55 -0700239 "xyz.openbmc_project.Network.IP.AddressOrigin.Static")
240 ? 1
241 : 0;
Ratan Guptad70f4532017-08-04 02:07:31 +0530242
William A. Kennington III4c008022018-10-12 17:18:14 -0700243 auto MACAddress = variant_ns::get<std::string>(variant);
Ratan Guptacc8feb42017-07-25 21:52:10 +0530244
Ratan Guptad70f4532017-08-04 02:07:31 +0530245 // it is expected here that we should get the valid data
246 // but we may also get the default values.
247 // Validation of the data is done by settings.
248 //
249 // if mac address is default mac address then
250 // don't send blank override.
Ratan Gupta8c31d232017-08-13 05:49:43 +0530251 if ((MACAddress == ipmi::network::DEFAULT_MAC_ADDRESS))
Ratan Guptad70f4532017-08-04 02:07:31 +0530252 {
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700253 std::memset(respptr->data, 0, SIZE_BOOT_OPTION);
Ratan Guptad70f4532017-08-04 02:07:31 +0530254 rc = -1;
255 return rc;
256 }
257 // if addr is static then ipaddress,gateway,prefix
258 // should not be default one,don't send blank override.
259 if (isStatic)
260 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700261 if ((ipAddress == ipmi::network::DEFAULT_ADDRESS) ||
262 (gateway == ipmi::network::DEFAULT_ADDRESS) || (!prefix))
Ratan Guptad70f4532017-08-04 02:07:31 +0530263 {
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700264 std::memset(respptr->data, 0, SIZE_BOOT_OPTION);
Ratan Guptad70f4532017-08-04 02:07:31 +0530265 rc = -1;
266 return rc;
267 }
268 }
269
Patrick Venture0b02be92018-08-31 11:55:55 -0700270 sscanf(
271 MACAddress.c_str(), ipmi::network::MAC_ADDRESS_FORMAT,
272 (respptr->data + MAC_OFFSET), (respptr->data + MAC_OFFSET + 1),
273 (respptr->data + MAC_OFFSET + 2), (respptr->data + MAC_OFFSET + 3),
274 (respptr->data + MAC_OFFSET + 4), (respptr->data + MAC_OFFSET + 5));
Ratan Guptadcb10672017-07-10 10:33:50 +0530275
Ratan Guptadcb10672017-07-10 10:33:50 +0530276 respptr->data[MAC_OFFSET + 6] = 0x00;
277
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700278 std::memcpy(respptr->data + ADDRTYPE_OFFSET, &isStatic,
279 sizeof(isStatic));
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530280
William A. Kennington III4c008022018-10-12 17:18:14 -0700281 uint8_t addressFamily =
282 (variant_ns::get<std::string>(properties["Type"]) ==
283 "xyz.openbmc_project.Network.IP.Protocol.IPv4")
284 ? AF_INET
285 : AF_INET6;
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530286
Patrick Venture0b02be92018-08-31 11:55:55 -0700287 addrSize = (addressFamily == AF_INET)
288 ? ipmi::network::IPV4_ADDRESS_SIZE_BYTE
289 : ipmi::network::IPV6_ADDRESS_SIZE_BYTE;
Ratan Guptadcb10672017-07-10 10:33:50 +0530290
291 // ipaddress and gateway would be in IPv4 format
Ratan Guptad70f4532017-08-04 02:07:31 +0530292 inet_pton(addressFamily, ipAddress.c_str(),
Patrick Venture0b02be92018-08-31 11:55:55 -0700293 (respptr->data + IPADDR_OFFSET));
Ratan Guptadcb10672017-07-10 10:33:50 +0530294
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530295 uint8_t prefixOffset = IPADDR_OFFSET + addrSize;
296
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700297 std::memcpy(respptr->data + prefixOffset, &prefix, sizeof(prefix));
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530298
299 uint8_t gatewayOffset = prefixOffset + sizeof(decltype(prefix));
300
Ratan Guptad70f4532017-08-04 02:07:31 +0530301 inet_pton(addressFamily, gateway.c_str(),
Patrick Venture0b02be92018-08-31 11:55:55 -0700302 (respptr->data + gatewayOffset));
Ratan Guptadcb10672017-07-10 10:33:50 +0530303 }
304 catch (InternalFailure& e)
305 {
306 commit<InternalFailure>();
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700307 std::memset(respptr->data, 0, SIZE_BOOT_OPTION);
Ratan Guptadcb10672017-07-10 10:33:50 +0530308 rc = -1;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500309 return rc;
310 }
311
Patrick Venture0b02be92018-08-31 11:55:55 -0700312 // PetiBoot-Specific
313 // If success then copy the first 9 bytes to the data
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700314 std::memcpy(respptr->data, net_conf_initial_bytes,
315 sizeof(net_conf_initial_bytes));
Ratan Guptafd28dd72016-08-01 04:58:01 -0500316
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700317 std::memcpy(respptr->data + ADDR_SIZE_OFFSET, &addrSize, sizeof(addrSize));
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530318
Ratan Guptafd28dd72016-08-01 04:58:01 -0500319#ifdef _IPMI_DEBUG_
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700320 std::printf("\n===Printing the IPMI Formatted Data========\n");
Ratan Guptafd28dd72016-08-01 04:58:01 -0500321
Ratan Guptadcb10672017-07-10 10:33:50 +0530322 for (uint8_t pos = 0; pos < index; pos++)
323 {
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700324 std::printf("%02x ", respptr->data[pos]);
Ratan Guptadcb10672017-07-10 10:33:50 +0530325 }
Ratan Guptafd28dd72016-08-01 04:58:01 -0500326#endif
327
Ratan Guptafd28dd72016-08-01 04:58:01 -0500328 return rc;
329}
330
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530331/** @brief convert IPv4 and IPv6 addresses from binary to text form.
332 * @param[in] family - IPv4/Ipv6
333 * @param[in] data - req data pointer.
334 * @param[in] offset - offset in the data.
335 * @param[in] addrSize - size of the data which needs to be read from offset.
336 * @returns address in text form.
337 */
338
Patrick Venture0b02be92018-08-31 11:55:55 -0700339std::string getAddrStr(uint8_t family, uint8_t* data, uint8_t offset,
340 uint8_t addrSize)
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530341{
342 char ipAddr[INET6_ADDRSTRLEN] = {};
343
Patrick Venture0b02be92018-08-31 11:55:55 -0700344 switch (family)
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530345 {
346 case AF_INET:
347 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700348 struct sockaddr_in addr4
349 {
350 };
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700351 std::memcpy(&addr4.sin_addr.s_addr, &data[offset], addrSize);
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530352
Patrick Venture0b02be92018-08-31 11:55:55 -0700353 inet_ntop(AF_INET, &addr4.sin_addr, ipAddr, INET_ADDRSTRLEN);
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530354
355 break;
356 }
357 case AF_INET6:
358 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700359 struct sockaddr_in6 addr6
360 {
361 };
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700362 std::memcpy(&addr6.sin6_addr.s6_addr, &data[offset], addrSize);
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530363
Patrick Venture0b02be92018-08-31 11:55:55 -0700364 inet_ntop(AF_INET6, &addr6.sin6_addr, ipAddr, INET6_ADDRSTRLEN);
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530365
366 break;
367 }
368 default:
369 {
370 return {};
371 }
372 }
373
374 return ipAddr;
375}
376
Ratan Guptadcb10672017-07-10 10:33:50 +0530377int setHostNetworkData(set_sys_boot_options_t* reqptr)
Ratan Guptafd28dd72016-08-01 04:58:01 -0500378{
Ratan Guptadcb10672017-07-10 10:33:50 +0530379 using namespace std::string_literals;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500380 std::string host_network_config;
Patrick Venture0b02be92018-08-31 11:55:55 -0700381 char mac[]{"00:00:00:00:00:00"};
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530382 std::string ipAddress, gateway;
Patrick Venture0b02be92018-08-31 11:55:55 -0700383 char addrOrigin{0};
384 uint8_t addrSize{0};
Ratan Guptadcb10672017-07-10 10:33:50 +0530385 std::string addressOrigin =
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530386 "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP";
Patrick Venture0b02be92018-08-31 11:55:55 -0700387 std::string addressType = "xyz.openbmc_project.Network.IP.Protocol.IPv4";
388 uint8_t prefix{0};
Ratan Guptadcb10672017-07-10 10:33:50 +0530389 uint32_t zeroCookie = 0;
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530390 uint8_t family = AF_INET;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500391
Patrick Venture0b02be92018-08-31 11:55:55 -0700392 // cookie starts from second byte
Ratan Guptafd28dd72016-08-01 04:58:01 -0500393 // version starts from sixth byte
394
Ratan Guptadcb10672017-07-10 10:33:50 +0530395 try
Ratan Guptafd28dd72016-08-01 04:58:01 -0500396 {
Ratan Guptadcb10672017-07-10 10:33:50 +0530397 do
398 {
399 // cookie == 0x21 0x70 0x62 0x21
400 if (memcmp(&(reqptr->data[COOKIE_OFFSET]),
Patrick Venture0b02be92018-08-31 11:55:55 -0700401 (net_conf_initial_bytes + COOKIE_OFFSET),
402 SIZE_COOKIE) != 0)
Ratan Guptadcb10672017-07-10 10:33:50 +0530403 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700404 // cookie == 0
405 if (memcmp(&(reqptr->data[COOKIE_OFFSET]), &zeroCookie,
406 SIZE_COOKIE) == 0)
Ratan Guptadcb10672017-07-10 10:33:50 +0530407 {
408 // need to zero out the network settings.
409 break;
410 }
411
412 log<level::ERR>("Invalid Cookie");
413 elog<InternalFailure>();
414 }
415
416 // vesion == 0x00 0x01
417 if (memcmp(&(reqptr->data[VERSION_OFFSET]),
Patrick Venture0b02be92018-08-31 11:55:55 -0700418 (net_conf_initial_bytes + VERSION_OFFSET),
419 SIZE_VERSION) != 0)
Ratan Guptadcb10672017-07-10 10:33:50 +0530420 {
421
422 log<level::ERR>("Invalid Version");
423 elog<InternalFailure>();
424 }
425
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700426 std::snprintf(
427 mac, SIZE_MAC, ipmi::network::MAC_ADDRESS_FORMAT,
428 reqptr->data[MAC_OFFSET], reqptr->data[MAC_OFFSET + 1],
429 reqptr->data[MAC_OFFSET + 2], reqptr->data[MAC_OFFSET + 3],
430 reqptr->data[MAC_OFFSET + 4], reqptr->data[MAC_OFFSET + 5]);
Ratan Guptadcb10672017-07-10 10:33:50 +0530431
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700432 std::memcpy(&addrOrigin, &(reqptr->data[ADDRTYPE_OFFSET]),
433 sizeof(decltype(addrOrigin)));
Ratan Guptadcb10672017-07-10 10:33:50 +0530434
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530435 if (addrOrigin)
Ratan Guptadcb10672017-07-10 10:33:50 +0530436 {
437 addressOrigin =
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530438 "xyz.openbmc_project.Network.IP.AddressOrigin.Static";
Ratan Guptadcb10672017-07-10 10:33:50 +0530439 }
440
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530441 // Get the address size
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700442 std::memcpy(&addrSize, &reqptr->data[ADDR_SIZE_OFFSET],
443 sizeof(addrSize));
Ratan Guptadcb10672017-07-10 10:33:50 +0530444
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530445 uint8_t prefixOffset = IPADDR_OFFSET + addrSize;
Ratan Guptadcb10672017-07-10 10:33:50 +0530446
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700447 std::memcpy(&prefix, &(reqptr->data[prefixOffset]),
448 sizeof(decltype(prefix)));
Ratan Guptadcb10672017-07-10 10:33:50 +0530449
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530450 uint8_t gatewayOffset = prefixOffset + sizeof(decltype(prefix));
451
Ratan Gupta8c31d232017-08-13 05:49:43 +0530452 if (addrSize != ipmi::network::IPV4_ADDRESS_SIZE_BYTE)
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530453 {
454 addressType = "xyz.openbmc_project.Network.IP.Protocol.IPv6";
455 family = AF_INET6;
456 }
457
Patrick Venture0b02be92018-08-31 11:55:55 -0700458 ipAddress =
459 getAddrStr(family, reqptr->data, IPADDR_OFFSET, addrSize);
Ratan Guptad70f4532017-08-04 02:07:31 +0530460
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530461 gateway = getAddrStr(family, reqptr->data, gatewayOffset, addrSize);
462
Patrick Venture0b02be92018-08-31 11:55:55 -0700463 } while (0);
Ratan Guptadcb10672017-07-10 10:33:50 +0530464
Patrick Venture0b02be92018-08-31 11:55:55 -0700465 // Cookie == 0 or it is a valid cookie
466 host_network_config += "ipaddress="s + ipAddress + ",prefix="s +
467 std::to_string(prefix) + ",gateway="s + gateway +
468 ",mac="s + mac + ",addressOrigin="s +
469 addressOrigin;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500470
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530471 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
472
473 auto ipObjectInfo = ipmi::getDbusObject(bus, IP_INTERFACE,
474 SETTINGS_ROOT, SETTINGS_MATCH);
475 auto macObjectInfo = ipmi::getDbusObject(bus, MAC_INTERFACE,
476 SETTINGS_ROOT, SETTINGS_MATCH);
Ratan Guptadcb10672017-07-10 10:33:50 +0530477 // set the dbus property
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530478 ipmi::setDbusProperty(bus, ipObjectInfo.second, ipObjectInfo.first,
Patrick Venture0b02be92018-08-31 11:55:55 -0700479 IP_INTERFACE, "Address", std::string(ipAddress));
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530480 ipmi::setDbusProperty(bus, ipObjectInfo.second, ipObjectInfo.first,
Patrick Venture0b02be92018-08-31 11:55:55 -0700481 IP_INTERFACE, "PrefixLength", prefix);
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530482 ipmi::setDbusProperty(bus, ipObjectInfo.second, ipObjectInfo.first,
Patrick Venture0b02be92018-08-31 11:55:55 -0700483 IP_INTERFACE, "Origin", addressOrigin);
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530484 ipmi::setDbusProperty(bus, ipObjectInfo.second, ipObjectInfo.first,
Patrick Venture0b02be92018-08-31 11:55:55 -0700485 IP_INTERFACE, "Gateway", std::string(gateway));
486 ipmi::setDbusProperty(
487 bus, ipObjectInfo.second, ipObjectInfo.first, IP_INTERFACE, "Type",
488 std::string("xyz.openbmc_project.Network.IP.Protocol.IPv4"));
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530489 ipmi::setDbusProperty(bus, macObjectInfo.second, macObjectInfo.first,
Patrick Venture0b02be92018-08-31 11:55:55 -0700490 MAC_INTERFACE, "MACAddress", std::string(mac));
Ratan Guptafd28dd72016-08-01 04:58:01 -0500491
Patrick Venture0b02be92018-08-31 11:55:55 -0700492 log<level::DEBUG>(
493 "Network configuration changed",
494 entry("NETWORKCONFIG=%s", host_network_config.c_str()));
Ratan Guptafd28dd72016-08-01 04:58:01 -0500495 }
Ratan Guptadcb10672017-07-10 10:33:50 +0530496 catch (InternalFailure& e)
497 {
498 commit<InternalFailure>();
499 return -1;
500 }
501
502 return 0;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500503}
504
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -0500505uint32_t getPOHCounter()
506{
507 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
508
Patrick Venture0b02be92018-08-31 11:55:55 -0700509 auto chassisStateObj =
510 ipmi::getDbusObject(bus, chassisPOHStateIntf, chassisStateRoot, match);
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -0500511
Patrick Venture0b02be92018-08-31 11:55:55 -0700512 auto service =
513 ipmi::getService(bus, chassisPOHStateIntf, chassisStateObj.first);
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -0500514
Patrick Venture0b02be92018-08-31 11:55:55 -0700515 auto propValue =
516 ipmi::getDbusProperty(bus, service, chassisStateObj.first,
517 chassisPOHStateIntf, pOHCounterProperty);
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -0500518
William A. Kennington III4c008022018-10-12 17:18:14 -0700519 return variant_ns::get<uint32_t>(propValue);
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -0500520}
521
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500522ipmi_ret_t ipmi_chassis_wildcard(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
523 ipmi_request_t request,
524 ipmi_response_t response,
525 ipmi_data_len_t data_len,
526 ipmi_context_t context)
Adriana Kobylak40814c62015-10-27 15:58:44 -0500527{
Adriana Kobylak40814c62015-10-27 15:58:44 -0500528 // Status code.
Nan Li70aa8d92016-08-29 00:11:10 +0800529 ipmi_ret_t rc = IPMI_CC_INVALID;
Adriana Kobylak40814c62015-10-27 15:58:44 -0500530 *data_len = 0;
531 return rc;
532}
533
Nan Li8d15fb42016-08-16 22:29:40 +0800534ipmi_ret_t ipmi_get_chassis_cap(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Patrick Venture0b02be92018-08-31 11:55:55 -0700535 ipmi_request_t request,
536 ipmi_response_t response,
537 ipmi_data_len_t data_len,
538 ipmi_context_t context)
Nan Li8d15fb42016-08-16 22:29:40 +0800539{
540 // sd_bus error
541 ipmi_ret_t rc = IPMI_CC_OK;
542
543 ipmi_chassis_cap_t chassis_cap{};
544
Yong Liae4b0402018-11-02 11:12:14 +0800545 if (*data_len != 0)
546 {
547 return IPMI_CC_REQ_DATA_LEN_INVALID;
548 }
549
Nan Li8d15fb42016-08-16 22:29:40 +0800550 *data_len = sizeof(ipmi_chassis_cap_t);
551
Yong Liae4b0402018-11-02 11:12:14 +0800552 try
553 {
554 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
Nan Li8d15fb42016-08-16 22:29:40 +0800555
Yong Liae4b0402018-11-02 11:12:14 +0800556 ipmi::DbusObjectInfo chassisCapObject =
557 ipmi::getDbusObject(bus, chassisCapIntf);
Nan Li8d15fb42016-08-16 22:29:40 +0800558
Yong Liae4b0402018-11-02 11:12:14 +0800559 // capabilities flags
560 // [7..4] - reserved
561 // [3] – 1b = provides power interlock (IPM 1.5)
562 // [2] – 1b = provides Diagnostic Interrupt (FP NMI)
563 // [1] – 1b = provides “Front Panel Lockout” (indicates that the chassis
564 // has capabilities
565 // to lock out external power control and reset button or
566 // front panel interfaces and/or detect tampering with those
567 // interfaces).
568 // [0] -1b = Chassis provides intrusion (physical security) sensor.
569 // set to default value 0x0.
570 ipmi::Value variant = ipmi::getDbusProperty(
571 bus, chassisCapObject.second, chassisCapObject.first,
572 chassisCapIntf, chassisCapFlagsProp);
573 chassis_cap.cap_flags = variant_ns::get<uint8_t>(variant);
Nan Li8d15fb42016-08-16 22:29:40 +0800574
Yong Liae4b0402018-11-02 11:12:14 +0800575 variant = ipmi::getDbusProperty(bus, chassisCapObject.second,
576 chassisCapObject.first, chassisCapIntf,
577 chassisFRUDevAddrProp);
578 // Chassis FRU info Device Address.
579 chassis_cap.fru_info_dev_addr = variant_ns::get<uint8_t>(variant);
Nan Li8d15fb42016-08-16 22:29:40 +0800580
Yong Liae4b0402018-11-02 11:12:14 +0800581 variant = ipmi::getDbusProperty(bus, chassisCapObject.second,
582 chassisCapObject.first, chassisCapIntf,
583 chassisSDRDevAddrProp);
584 // Chassis SDR Device Address.
585 chassis_cap.sdr_dev_addr = variant_ns::get<uint8_t>(variant);
Nan Li8d15fb42016-08-16 22:29:40 +0800586
Yong Liae4b0402018-11-02 11:12:14 +0800587 variant = ipmi::getDbusProperty(bus, chassisCapObject.second,
588 chassisCapObject.first, chassisCapIntf,
589 chassisSELDevAddrProp);
590 // Chassis SEL Device Address.
591 chassis_cap.sel_dev_addr = variant_ns::get<uint8_t>(variant);
Nan Li8d15fb42016-08-16 22:29:40 +0800592
Yong Liae4b0402018-11-02 11:12:14 +0800593 variant = ipmi::getDbusProperty(bus, chassisCapObject.second,
594 chassisCapObject.first, chassisCapIntf,
595 chassisSMDevAddrProp);
596 // Chassis System Management Device Address.
597 chassis_cap.system_management_dev_addr =
598 variant_ns::get<uint8_t>(variant);
Nan Li8d15fb42016-08-16 22:29:40 +0800599
Yong Liae4b0402018-11-02 11:12:14 +0800600 variant = ipmi::getDbusProperty(bus, chassisCapObject.second,
601 chassisCapObject.first, chassisCapIntf,
602 chassisBridgeDevAddrProp);
603 // Chassis Bridge Device Address.
604 chassis_cap.bridge_dev_addr = variant_ns::get<uint8_t>(variant);
605 uint8_t* respP = reinterpret_cast<uint8_t*>(response);
606 uint8_t* chassisP = reinterpret_cast<uint8_t*>(&chassis_cap);
607 std::copy(chassisP, chassisP + *data_len, respP);
608 }
609 catch (std::exception& e)
610 {
611 log<level::ERR>(e.what());
612 rc = IPMI_CC_UNSPECIFIED_ERROR;
613 *data_len = 0;
614 return rc;
615 }
616
617 return rc;
618}
619
620ipmi_ret_t ipmi_set_chassis_cap(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
621 ipmi_request_t request,
622 ipmi_response_t response,
623 ipmi_data_len_t data_len,
624 ipmi_context_t context)
625{
626 ipmi_ret_t rc = IPMI_CC_OK;
627
628 if (*data_len != sizeof(ipmi_chassis_cap_t))
629 {
630 log<level::ERR>("Unsupported request length",
631 entry("LEN=0x%x", *data_len));
632 *data_len = 0;
633 return IPMI_CC_REQ_DATA_LEN_INVALID;
634 }
635
636 ipmi_chassis_cap_t* chassisCap = static_cast<ipmi_chassis_cap_t*>(request);
637
638 *data_len = 0;
639
640 // check input data
641 if (0 != (chassisCap->cap_flags & ~chassisCapFlagMask))
642 {
643 log<level::ERR>("Unsupported request parameter(CAP Flags)",
644 entry("REQ=0x%x", chassisCap->cap_flags));
645 return IPMI_CC_INVALID_FIELD_REQUEST;
646 }
647
648 if (0 != (chassisCap->fru_info_dev_addr & ~chassisCapAddrMask))
649 {
650 log<level::ERR>("Unsupported request parameter(FRU Addr)",
651 entry("REQ=0x%x", chassisCap->fru_info_dev_addr));
652 return IPMI_CC_INVALID_FIELD_REQUEST;
653 }
654
655 if (0 != (chassisCap->sdr_dev_addr & ~chassisCapAddrMask))
656 {
657 log<level::ERR>("Unsupported request parameter(SDR Addr)",
658 entry("REQ=0x%x", chassisCap->sdr_dev_addr));
659 return IPMI_CC_INVALID_FIELD_REQUEST;
660 }
661
662 if (0 != (chassisCap->sel_dev_addr & ~chassisCapAddrMask))
663 {
664 log<level::ERR>("Unsupported request parameter(SEL Addr)",
665 entry("REQ=0x%x", chassisCap->sel_dev_addr));
666 return IPMI_CC_INVALID_FIELD_REQUEST;
667 }
668
669 if (0 != (chassisCap->system_management_dev_addr & ~chassisCapAddrMask))
670 {
671 log<level::ERR>(
672 "Unsupported request parameter(SM Addr)",
673 entry("REQ=0x%x", chassisCap->system_management_dev_addr));
674 return IPMI_CC_INVALID_FIELD_REQUEST;
675 }
676
677 if (0 != (chassisCap->bridge_dev_addr & ~chassisCapAddrMask))
678 {
679 log<level::ERR>("Unsupported request parameter(Bridge Addr)",
680 entry("REQ=0x%x", chassisCap->bridge_dev_addr));
681 return IPMI_CC_INVALID_FIELD_REQUEST;
682 }
683
684 try
685 {
686 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
687 ipmi::DbusObjectInfo chassisCapObject =
688 ipmi::getDbusObject(bus, chassisCapIntf);
689
690 ipmi::setDbusProperty(bus, chassisCapObject.second,
691 chassisCapObject.first, chassisCapIntf,
692 chassisCapFlagsProp, chassisCap->cap_flags);
693
694 ipmi::setDbusProperty(bus, chassisCapObject.second,
695 chassisCapObject.first, chassisCapIntf,
696 chassisFRUDevAddrProp,
697 chassisCap->fru_info_dev_addr);
698
699 ipmi::setDbusProperty(bus, chassisCapObject.second,
700 chassisCapObject.first, chassisCapIntf,
701 chassisSDRDevAddrProp, chassisCap->sdr_dev_addr);
702
703 ipmi::setDbusProperty(bus, chassisCapObject.second,
704 chassisCapObject.first, chassisCapIntf,
705 chassisSELDevAddrProp, chassisCap->sel_dev_addr);
706
707 ipmi::setDbusProperty(bus, chassisCapObject.second,
708 chassisCapObject.first, chassisCapIntf,
709 chassisSMDevAddrProp,
710 chassisCap->system_management_dev_addr);
711
712 ipmi::setDbusProperty(bus, chassisCapObject.second,
713 chassisCapObject.first, chassisCapIntf,
714 chassisBridgeDevAddrProp,
715 chassisCap->bridge_dev_addr);
716 }
717 catch (std::exception& e)
718 {
719 log<level::ERR>(e.what());
720 rc = IPMI_CC_UNSPECIFIED_ERROR;
721 return rc;
722 }
Nan Li8d15fb42016-08-16 22:29:40 +0800723
724 return rc;
725}
726
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530727//------------------------------------------
728// Calls into Host State Manager Dbus object
729//------------------------------------------
730int initiate_state_transition(State::Host::Transition transition)
vishwa36993272015-11-20 12:43:49 -0600731{
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500732 // OpenBMC Host State Manager dbus framework
Patrick Venture0b02be92018-08-31 11:55:55 -0700733 constexpr auto HOST_STATE_MANAGER_ROOT = "/xyz/openbmc_project/state/host0";
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500734 constexpr auto HOST_STATE_MANAGER_IFACE = "xyz.openbmc_project.State.Host";
Patrick Venture0b02be92018-08-31 11:55:55 -0700735 constexpr auto DBUS_PROPERTY_IFACE = "org.freedesktop.DBus.Properties";
736 constexpr auto PROPERTY = "RequestedHostTransition";
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530737
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500738 // sd_bus error
739 int rc = 0;
Patrick Venture0b02be92018-08-31 11:55:55 -0700740 char* busname = NULL;
vishwa36993272015-11-20 12:43:49 -0600741
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500742 // SD Bus error report mechanism.
743 sd_bus_error bus_error = SD_BUS_ERROR_NULL;
vishwa36993272015-11-20 12:43:49 -0600744
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500745 // Gets a hook onto either a SYSTEM or SESSION bus
Patrick Venture0b02be92018-08-31 11:55:55 -0700746 sd_bus* bus_type = ipmid_get_sd_bus_connection();
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500747 rc = mapper_get_service(bus_type, HOST_STATE_MANAGER_ROOT, &busname);
748 if (rc < 0)
749 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700750 log<level::ERR>(
751 "Failed to get bus name",
752 entry("ERRNO=0x%X, OBJPATH=%s", -rc, HOST_STATE_MANAGER_ROOT));
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500753 return rc;
754 }
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530755
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500756 // Convert to string equivalent of the passed in transition enum.
757 auto request = State::convertForMessage(transition);
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530758
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500759 rc = sd_bus_call_method(bus_type, // On the system bus
760 busname, // Service to contact
761 HOST_STATE_MANAGER_ROOT, // Object path
762 DBUS_PROPERTY_IFACE, // Interface name
763 "Set", // Method to be called
764 &bus_error, // object to return error
765 nullptr, // Response buffer if any
766 "ssv", // Takes 3 arguments
Patrick Venture0b02be92018-08-31 11:55:55 -0700767 HOST_STATE_MANAGER_IFACE, PROPERTY, "s",
768 request.c_str());
769 if (rc < 0)
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500770 {
771 log<level::ERR>("Failed to initiate transition",
Aditya Saripalli5fb14602017-11-09 14:46:27 +0530772 entry("ERRNO=0x%X, REQUEST=%s", -rc, request.c_str()));
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500773 }
774 else
775 {
776 log<level::INFO>("Transition request initiated successfully");
777 }
vishwa36993272015-11-20 12:43:49 -0600778
779 sd_bus_error_free(&bus_error);
Sergey Solomineb9b8142016-08-23 09:07:28 -0500780 free(busname);
vishwa36993272015-11-20 12:43:49 -0600781
Sergey Solomineb9b8142016-08-23 09:07:28 -0500782 return rc;
vishwa36993272015-11-20 12:43:49 -0600783}
784
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500785namespace power_policy
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500786{
Nan Lifdd8ec52016-08-28 03:57:40 +0800787
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500788using namespace sdbusplus::xyz::openbmc_project::Control::Power::server;
789using IpmiValue = uint8_t;
790using DbusValue = RestorePolicy::Policy;
Nan Lifdd8ec52016-08-28 03:57:40 +0800791
Patrick Venture0b02be92018-08-31 11:55:55 -0700792std::map<DbusValue, IpmiValue> dbusToIpmi = {
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500793 {RestorePolicy::Policy::AlwaysOff, 0x00},
794 {RestorePolicy::Policy::Restore, 0x01},
Patrick Venture0b02be92018-08-31 11:55:55 -0700795 {RestorePolicy::Policy::AlwaysOn, 0x02}};
Nan Lifdd8ec52016-08-28 03:57:40 +0800796
Yong Lic6713cf2018-09-12 12:35:13 +0800797static constexpr uint8_t noChange = 0x03;
798static constexpr uint8_t allSupport = 0x01 | 0x02 | 0x04;
799static constexpr uint8_t policyBitMask = 0x07;
800static constexpr uint8_t setPolicyReqLen = 1;
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500801} // namespace power_policy
Nan Lifdd8ec52016-08-28 03:57:40 +0800802
803//----------------------------------------------------------------------
804// Get Chassis Status commands
805//----------------------------------------------------------------------
806ipmi_ret_t ipmi_get_chassis_status(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500807 ipmi_request_t request,
808 ipmi_response_t response,
809 ipmi_data_len_t data_len,
810 ipmi_context_t context)
Nan Lifdd8ec52016-08-28 03:57:40 +0800811{
Patrick Venture0b02be92018-08-31 11:55:55 -0700812 const char* objname = "/org/openbmc/control/power0";
813 const char* intf = "org.openbmc.control.Power";
Nan Lifdd8ec52016-08-28 03:57:40 +0800814
Patrick Venture0b02be92018-08-31 11:55:55 -0700815 sd_bus* bus = NULL;
816 sd_bus_message* reply = NULL;
Nan Lifdd8ec52016-08-28 03:57:40 +0800817 int r = 0;
818 int pgood = 0;
Patrick Venture0b02be92018-08-31 11:55:55 -0700819 char* busname = NULL;
Nan Lifdd8ec52016-08-28 03:57:40 +0800820 ipmi_ret_t rc = IPMI_CC_OK;
821 ipmi_get_chassis_status_t chassis_status{};
822
Nan Lifdd8ec52016-08-28 03:57:40 +0800823 uint8_t s = 0;
824
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500825 using namespace chassis::internal;
826 using namespace chassis::internal::cache;
827 using namespace power_policy;
828
Deepak Kodihallie6027092017-08-27 08:13:37 -0500829 const auto& powerRestoreSetting = objects.map.at(powerRestoreIntf).front();
Patrick Venture0b02be92018-08-31 11:55:55 -0700830 auto method = dbus.new_method_call(
831 objects.service(powerRestoreSetting, powerRestoreIntf).c_str(),
832 powerRestoreSetting.c_str(), ipmi::PROP_INTF, "Get");
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500833 method.append(powerRestoreIntf, "PowerRestorePolicy");
834 auto resp = dbus.call(method);
835 if (resp.is_method_error())
836 {
837 log<level::ERR>("Error in PowerRestorePolicy Get");
838 report<InternalFailure>();
839 *data_len = 0;
840 return IPMI_CC_UNSPECIFIED_ERROR;
841 }
842 sdbusplus::message::variant<std::string> result;
843 resp.read(result);
William A. Kennington III4c008022018-10-12 17:18:14 -0700844 auto powerRestore = RestorePolicy::convertPolicyFromString(
845 variant_ns::get<std::string>(result));
Nan Lifdd8ec52016-08-28 03:57:40 +0800846
847 *data_len = 4;
848
Tom Joseph63a00512017-08-09 23:39:59 +0530849 bus = ipmid_get_sd_bus_connection();
850
Nan Lifdd8ec52016-08-28 03:57:40 +0800851 r = mapper_get_service(bus, objname, &busname);
Patrick Venture0b02be92018-08-31 11:55:55 -0700852 if (r < 0)
853 {
854 log<level::ERR>("Failed to get bus name", entry("ERRNO=0x%X", -r));
Nan Lifdd8ec52016-08-28 03:57:40 +0800855 rc = IPMI_CC_UNSPECIFIED_ERROR;
856 goto finish;
857 }
858
Patrick Venture0b02be92018-08-31 11:55:55 -0700859 r = sd_bus_get_property(bus, busname, objname, intf, "pgood", NULL, &reply,
860 "i");
861 if (r < 0)
862 {
Aditya Saripalli5fb14602017-11-09 14:46:27 +0530863 log<level::ERR>("Failed to call sd_bus_get_property",
Patrick Venture0b02be92018-08-31 11:55:55 -0700864 entry("PROPERTY=%s", "pgood"), entry("ERRNO=0x%X", -r),
865 entry("BUS=%s", busname), entry("PATH=%s", objname),
Aditya Saripalli5fb14602017-11-09 14:46:27 +0530866 entry("INTERFACE=%s", intf));
Nan Lifdd8ec52016-08-28 03:57:40 +0800867 rc = IPMI_CC_UNSPECIFIED_ERROR;
868 goto finish;
869 }
870
871 r = sd_bus_message_read(reply, "i", &pgood);
Patrick Venture0b02be92018-08-31 11:55:55 -0700872 if (r < 0)
873 {
874 log<level::ERR>("Failed to read sensor:", entry("ERRNO=0x%X", -r));
Nan Lifdd8ec52016-08-28 03:57:40 +0800875 rc = IPMI_CC_UNSPECIFIED_ERROR;
876 goto finish;
877 }
878
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500879 s = dbusToIpmi.at(powerRestore);
Nan Lifdd8ec52016-08-28 03:57:40 +0800880
881 // Current Power State
882 // [7] reserved
883 // [6..5] power restore policy
884 // 00b = chassis stays powered off after AC/mains returns
885 // 01b = after AC returns, power is restored to the state that was
886 // in effect when AC/mains was lost.
887 // 10b = chassis always powers up after AC/mains returns
888 // 11b = unknow
889 // Set to 00b, by observing the hardware behavior.
Patrick Venture0b02be92018-08-31 11:55:55 -0700890 // Do we need to define a dbus property to identify the restore
891 // policy?
Nan Lifdd8ec52016-08-28 03:57:40 +0800892
893 // [4] power control fault
894 // 1b = controller attempted to turn system power on or off, but
895 // system did not enter desired state.
896 // Set to 0b, since We don't support it..
897
898 // [3] power fault
899 // 1b = fault detected in main power subsystem.
900 // set to 0b. for we don't support it.
901
902 // [2] 1b = interlock (chassis is presently shut down because a chassis
903 // panel interlock switch is active). (IPMI 1.5)
904 // set to 0b, for we don't support it.
905
906 // [1] power overload
907 // 1b = system shutdown because of power overload condition.
908 // set to 0b, for we don't support it.
909
910 // [0] power is on
911 // 1b = system power is on
912 // 0b = system power is off(soft-off S4/S5, or mechanical off)
913
Patrick Venture0b02be92018-08-31 11:55:55 -0700914 chassis_status.cur_power_state = ((s & 0x3) << 5) | (pgood & 0x1);
Nan Lifdd8ec52016-08-28 03:57:40 +0800915
916 // Last Power Event
917 // [7..5] – reserved
918 // [4] – 1b = last ‘Power is on’ state was entered via IPMI command
919 // [3] – 1b = last power down caused by power fault
920 // [2] – 1b = last power down caused by a power interlock being activated
921 // [1] – 1b = last power down caused by a Power overload
922 // [0] – 1b = AC failed
923 // set to 0x0, for we don't support these fields.
924
925 chassis_status.last_power_event = 0;
926
927 // Misc. Chassis State
928 // [7] – reserved
929 // [6] – 1b = Chassis Identify command and state info supported (Optional)
930 // 0b = Chassis Identify command support unspecified via this command.
931 // (The Get Command Support command , if implemented, would still
932 // indicate support for the Chassis Identify command)
Patrick Venture0b02be92018-08-31 11:55:55 -0700933 // [5..4] – Chassis Identify State. Mandatory when bit[6] =1b, reserved
934 // (return
Nan Lifdd8ec52016-08-28 03:57:40 +0800935 // as 00b) otherwise. Returns the present chassis identify state.
936 // Refer to the Chassis Identify command for more info.
937 // 00b = chassis identify state = Off
938 // 01b = chassis identify state = Temporary(timed) On
939 // 10b = chassis identify state = Indefinite On
940 // 11b = reserved
941 // [3] – 1b = Cooling/fan fault detected
942 // [2] – 1b = Drive Fault
943 // [1] – 1b = Front Panel Lockout active (power off and reset via chassis
944 // push-buttons disabled.)
945 // [0] – 1b = Chassis Intrusion active
946 // set to 0, for we don't support them.
947 chassis_status.misc_power_state = 0;
948
949 // Front Panel Button Capabilities and disable/enable status(Optional)
950 // set to 0, for we don't support them.
951 chassis_status.front_panel_button_cap_status = 0;
952
953 // Pack the actual response
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700954 std::memcpy(response, &chassis_status, *data_len);
Nan Lifdd8ec52016-08-28 03:57:40 +0800955
956finish:
957 free(busname);
958 reply = sd_bus_message_unref(reply);
959
960 return rc;
961}
Chris Austen7888c4d2015-12-03 15:26:20 -0600962
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +0530963//-------------------------------------------------------------
964// Send a command to SoftPowerOff application to stop any timer
965//-------------------------------------------------------------
966int stop_soft_off_timer()
967{
Patrick Venture0b02be92018-08-31 11:55:55 -0700968 constexpr auto iface = "org.freedesktop.DBus.Properties";
969 constexpr auto soft_off_iface = "xyz.openbmc_project.Ipmi.Internal."
970 "SoftPowerOff";
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +0530971
Patrick Venture0b02be92018-08-31 11:55:55 -0700972 constexpr auto property = "ResponseReceived";
973 constexpr auto value = "xyz.openbmc_project.Ipmi.Internal."
974 "SoftPowerOff.HostResponse.HostShutdown";
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +0530975
976 // Get the system bus where most system services are provided.
977 auto bus = ipmid_get_sd_bus_connection();
978
979 // Get the service name
Andrew Geissler2b4e4592017-06-08 11:18:35 -0500980 // TODO openbmc/openbmc#1661 - Mapper refactor
981 //
982 // See openbmc/openbmc#1743 for some details but high level summary is that
983 // for now the code will directly call the soft off interface due to a
984 // race condition with mapper usage
985 //
Patrick Venture0b02be92018-08-31 11:55:55 -0700986 // char *busname = nullptr;
987 // auto r = mapper_get_service(bus, SOFTOFF_OBJPATH, &busname);
988 // if (r < 0)
Andrew Geissler2b4e4592017-06-08 11:18:35 -0500989 //{
990 // fprintf(stderr, "Failed to get %s bus name: %s\n",
Aditya Saripalli5fb14602017-11-09 14:46:27 +0530991 // SOFTOFF_OBJPATH, -r);
Andrew Geissler2b4e4592017-06-08 11:18:35 -0500992 // return r;
993 //}
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +0530994
995 // No error object or reply expected.
Andrew Geissler2b4e4592017-06-08 11:18:35 -0500996 int rc = sd_bus_call_method(bus, SOFTOFF_BUSNAME, SOFTOFF_OBJPATH, iface,
Patrick Venture0b02be92018-08-31 11:55:55 -0700997 "Set", nullptr, nullptr, "ssv", soft_off_iface,
998 property, "s", value);
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +0530999 if (rc < 0)
1000 {
Aditya Saripalli5fb14602017-11-09 14:46:27 +05301001 log<level::ERR>("Failed to set property in SoftPowerOff object",
1002 entry("ERRNO=0x%X", -rc));
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +05301003 }
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001004
Patrick Venture0b02be92018-08-31 11:55:55 -07001005 // TODO openbmc/openbmc#1661 - Mapper refactor
1006 // free(busname);
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +05301007 return rc;
1008}
1009
vishwa36993272015-11-20 12:43:49 -06001010//----------------------------------------------------------------------
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001011// Create file to indicate there is no need for softoff notification to host
1012//----------------------------------------------------------------------
1013void indicate_no_softoff_needed()
1014{
1015 fs::path path{HOST_INBAND_REQUEST_DIR};
1016 if (!fs::is_directory(path))
1017 {
1018 fs::create_directory(path);
1019 }
1020
1021 // Add the host instance (default 0 for now) to the file name
1022 std::string file{HOST_INBAND_REQUEST_FILE};
Patrick Venture0b02be92018-08-31 11:55:55 -07001023 auto size = std::snprintf(nullptr, 0, file.c_str(), 0);
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001024 size++; // null
1025 std::unique_ptr<char[]> buf(new char[size]);
Patrick Venture0b02be92018-08-31 11:55:55 -07001026 std::snprintf(buf.get(), size, file.c_str(), 0);
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001027
1028 // Append file name to directory and create it
1029 path /= buf.get();
1030 std::ofstream(path.c_str());
1031}
1032
1033//----------------------------------------------------------------------
vishwa36993272015-11-20 12:43:49 -06001034// Chassis Control commands
1035//----------------------------------------------------------------------
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001036ipmi_ret_t ipmi_chassis_control(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1037 ipmi_request_t request,
1038 ipmi_response_t response,
1039 ipmi_data_len_t data_len,
1040 ipmi_context_t context)
vishwa36993272015-11-20 12:43:49 -06001041{
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001042 // Error from power off.
1043 int rc = 0;
vishwa36993272015-11-20 12:43:49 -06001044
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001045 // No response for this command.
vishwa36993272015-11-20 12:43:49 -06001046 *data_len = 0;
1047
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001048 // Catch the actual operaton by peeking into request buffer
Patrick Venture0b02be92018-08-31 11:55:55 -07001049 uint8_t chassis_ctrl_cmd = *(uint8_t*)request;
vishwa36993272015-11-20 12:43:49 -06001050
Patrick Venture0b02be92018-08-31 11:55:55 -07001051 switch (chassis_ctrl_cmd)
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001052 {
1053 case CMD_POWER_ON:
1054 rc = initiate_state_transition(State::Host::Transition::On);
1055 break;
1056 case CMD_POWER_OFF:
Vishwanatha Subbanna8b26d352017-08-04 18:35:18 +05301057 // This path would be hit in 2 conditions.
1058 // 1: When user asks for power off using ipmi chassis command 0x04
1059 // 2: Host asking for power off post shutting down.
1060
1061 // If it's a host requested power off, then need to nudge Softoff
1062 // application that it needs to stop the watchdog timer if running.
1063 // If it is a user requested power off, then this is not really
1064 // needed. But then we need to differentiate between user and host
1065 // calling this same command
1066
1067 // For now, we are going ahead with trying to nudge the soft off and
1068 // interpret the failure to do so as a non softoff case
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001069 rc = stop_soft_off_timer();
Vishwanatha Subbanna8b26d352017-08-04 18:35:18 +05301070
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001071 // Only request the Off transition if the soft power off
1072 // application is not running
1073 if (rc < 0)
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001074 {
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001075 // First create a file to indicate to the soft off application
Vishwanatha Subbanna8b26d352017-08-04 18:35:18 +05301076 // that it should not run. Not doing this will result in State
1077 // manager doing a default soft power off when asked for power
1078 // off.
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001079 indicate_no_softoff_needed();
1080
1081 // Now request the shutdown
1082 rc = initiate_state_transition(State::Host::Transition::Off);
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001083 }
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001084 else
1085 {
Vishwanatha Subbanna8b26d352017-08-04 18:35:18 +05301086 log<level::INFO>("Soft off is running, so let shutdown target "
1087 "stop the host");
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001088 }
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001089 break;
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +05301090
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001091 case CMD_HARD_RESET:
1092 case CMD_POWER_CYCLE:
1093 // SPEC has a section that says certain implementations can trigger
1094 // PowerOn if power is Off when a command to power cycle is
1095 // requested
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001096
1097 // First create a file to indicate to the soft off application
1098 // that it should not run since this is a direct user initiated
1099 // power reboot request (i.e. a reboot request that is not
1100 // originating via a soft power off SMS request)
1101 indicate_no_softoff_needed();
1102
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001103 rc = initiate_state_transition(State::Host::Transition::Reboot);
1104 break;
Vishwanatha Subbanna8b26d352017-08-04 18:35:18 +05301105
1106 case CMD_SOFT_OFF_VIA_OVER_TEMP:
1107 // Request Host State Manager to do a soft power off
1108 rc = initiate_state_transition(State::Host::Transition::Off);
1109 break;
1110
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001111 default:
1112 {
Aditya Saripalli5fb14602017-11-09 14:46:27 +05301113 log<level::ERR>("Invalid Chassis Control command",
1114 entry("CMD=0x%X", chassis_ctrl_cmd));
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001115 rc = -1;
1116 }
1117 }
vishwa36993272015-11-20 12:43:49 -06001118
Patrick Venture0b02be92018-08-31 11:55:55 -07001119 return ((rc < 0) ? IPMI_CC_INVALID : IPMI_CC_OK);
vishwa36993272015-11-20 12:43:49 -06001120}
1121
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001122/** @brief Return D-Bus connection string to enclosure identify LED object
1123 *
1124 * @param[in, out] connection - connection to D-Bus object
1125 * @return a IPMI return code
1126 */
1127std::string getEnclosureIdentifyConnection()
Tom Joseph5110c122018-03-23 17:55:40 +05301128{
Tom Joseph5110c122018-03-23 17:55:40 +05301129 // lookup enclosure_identify group owner(s) in mapper
1130 auto mapperCall = chassis::internal::dbus.new_method_call(
Patrick Venture0b02be92018-08-31 11:55:55 -07001131 ipmi::MAPPER_BUS_NAME, ipmi::MAPPER_OBJ, ipmi::MAPPER_INTF,
1132 "GetObject");
Tom Joseph5110c122018-03-23 17:55:40 +05301133
1134 mapperCall.append(identify_led_object_name);
Patrick Venture0b02be92018-08-31 11:55:55 -07001135 static const std::vector<std::string> interfaces = {
1136 "xyz.openbmc_project.Led.Group"};
Tom Joseph5110c122018-03-23 17:55:40 +05301137 mapperCall.append(interfaces);
1138 auto mapperReply = chassis::internal::dbus.call(mapperCall);
1139 if (mapperReply.is_method_error())
1140 {
1141 log<level::ERR>("Chassis Identify: Error communicating to mapper.");
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001142 elog<InternalFailure>();
Tom Joseph5110c122018-03-23 17:55:40 +05301143 }
1144 std::vector<std::pair<std::string, std::vector<std::string>>> mapperResp;
1145 mapperReply.read(mapperResp);
1146
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001147 if (mapperResp.size() != encIdentifyObjectsSize)
Tom Joseph5110c122018-03-23 17:55:40 +05301148 {
Patrick Venture0b02be92018-08-31 11:55:55 -07001149 log<level::ERR>(
1150 "Invalid number of enclosure identify objects.",
1151 entry("ENC_IDENTITY_OBJECTS_SIZE=%d", mapperResp.size()));
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001152 elog<InternalFailure>();
1153 }
1154 auto pair = mapperResp[encIdentifyObjectsSize - 1];
1155 return pair.first;
1156}
Tom Joseph5110c122018-03-23 17:55:40 +05301157
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001158/** @brief Turn On/Off enclosure identify LED
1159 *
1160 * @param[in] flag - true to turn on LED, false to turn off
1161 * @return a IPMI return code
1162 */
1163void enclosureIdentifyLed(bool flag)
1164{
1165 using namespace chassis::internal;
1166 std::string connection = std::move(getEnclosureIdentifyConnection());
Patrick Venture0b02be92018-08-31 11:55:55 -07001167 auto led =
1168 dbus.new_method_call(connection.c_str(), identify_led_object_name,
1169 "org.freedesktop.DBus.Properties", "Set");
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001170 led.append("xyz.openbmc_project.Led.Group", "Asserted",
Patrick Venture0b02be92018-08-31 11:55:55 -07001171 sdbusplus::message::variant<bool>(flag));
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001172 auto ledReply = dbus.call(led);
1173 if (ledReply.is_method_error())
1174 {
1175 log<level::ERR>("Chassis Identify: Error Setting State On/Off\n",
Patrick Venture0b02be92018-08-31 11:55:55 -07001176 entry("LED_STATE=%d", flag));
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001177 elog<InternalFailure>();
1178 }
1179}
1180
1181/** @brief Callback method to turn off LED
1182 */
1183void enclosureIdentifyLedOff()
1184{
1185 try
1186 {
1187 enclosureIdentifyLed(false);
1188 }
1189 catch (const InternalFailure& e)
1190 {
1191 report<InternalFailure>();
1192 }
1193}
1194
1195/** @brief Create timer to turn on and off the enclosure LED
1196 */
1197void createIdentifyTimer()
1198{
1199 if (!identifyTimer)
1200 {
Vernon Mauery1181af72018-10-08 12:05:00 -07001201 identifyTimer =
1202 std::make_unique<phosphor::Timer>(enclosureIdentifyLedOff);
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001203 }
1204}
1205
1206ipmi_ret_t ipmi_chassis_identify(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1207 ipmi_request_t request,
1208 ipmi_response_t response,
1209 ipmi_data_len_t data_len,
1210 ipmi_context_t context)
1211{
1212 if (*data_len > chassisIdentifyReqLength)
1213 {
1214 return IPMI_CC_REQ_DATA_LEN_INVALID;
1215 }
Patrick Venture0b02be92018-08-31 11:55:55 -07001216 uint8_t identifyInterval =
1217 *data_len > identifyIntervalPos
1218 ? (static_cast<uint8_t*>(request))[identifyIntervalPos]
1219 : DEFAULT_IDENTIFY_TIME_OUT;
1220 bool forceIdentify =
1221 (*data_len == chassisIdentifyReqLength)
1222 ? (static_cast<uint8_t*>(request))[forceIdentifyPos] & 0x01
1223 : false;
Tom Josephbed26992018-07-31 23:00:24 +05301224
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001225 if (identifyInterval || forceIdentify)
1226 {
1227 // stop the timer if already started, for force identify we should
1228 // not turn off LED
Vernon Mauery1181af72018-10-08 12:05:00 -07001229 identifyTimer->stop();
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001230 try
Tom Joseph5110c122018-03-23 17:55:40 +05301231 {
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001232 enclosureIdentifyLed(true);
1233 }
1234 catch (const InternalFailure& e)
1235 {
1236 report<InternalFailure>();
1237 return IPMI_CC_RESPONSE_ERROR;
Tom Joseph5110c122018-03-23 17:55:40 +05301238 }
1239
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001240 if (forceIdentify)
Tom Joseph5110c122018-03-23 17:55:40 +05301241 {
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001242 return IPMI_CC_OK;
1243 }
1244 // start the timer
1245 auto time = std::chrono::duration_cast<std::chrono::microseconds>(
Patrick Venture0b02be92018-08-31 11:55:55 -07001246 std::chrono::seconds(identifyInterval));
Vernon Mauery1181af72018-10-08 12:05:00 -07001247 identifyTimer->start(time);
Tom Joseph5110c122018-03-23 17:55:40 +05301248 }
Tom Josephbed26992018-07-31 23:00:24 +05301249 else if (!identifyInterval)
1250 {
Vernon Mauery1181af72018-10-08 12:05:00 -07001251 identifyTimer->stop();
Tom Josephbed26992018-07-31 23:00:24 +05301252 enclosureIdentifyLedOff();
1253 }
Tom Joseph5110c122018-03-23 17:55:40 +05301254 return IPMI_CC_OK;
1255}
1256
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001257namespace boot_options
1258{
1259
1260using namespace sdbusplus::xyz::openbmc_project::Control::Boot::server;
1261using IpmiValue = uint8_t;
1262constexpr auto ipmiDefault = 0;
1263
Patrick Venture0b02be92018-08-31 11:55:55 -07001264std::map<IpmiValue, Source::Sources> sourceIpmiToDbus = {
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001265 {0x01, Source::Sources::Network},
1266 {0x02, Source::Sources::Disk},
1267 {0x05, Source::Sources::ExternalMedia},
Patrick Venture0b02be92018-08-31 11:55:55 -07001268 {ipmiDefault, Source::Sources::Default}};
shgoupfd84fbbf2015-12-17 10:05:51 +08001269
Patrick Venture0b02be92018-08-31 11:55:55 -07001270std::map<IpmiValue, Mode::Modes> modeIpmiToDbus = {
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001271 {0x03, Mode::Modes::Safe},
1272 {0x06, Mode::Modes::Setup},
Patrick Venture0b02be92018-08-31 11:55:55 -07001273 {ipmiDefault, Mode::Modes::Regular}};
shgoupfd84fbbf2015-12-17 10:05:51 +08001274
Patrick Venture0b02be92018-08-31 11:55:55 -07001275std::map<Source::Sources, IpmiValue> sourceDbusToIpmi = {
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001276 {Source::Sources::Network, 0x01},
1277 {Source::Sources::Disk, 0x02},
1278 {Source::Sources::ExternalMedia, 0x05},
Patrick Venture0b02be92018-08-31 11:55:55 -07001279 {Source::Sources::Default, ipmiDefault}};
shgoupfd84fbbf2015-12-17 10:05:51 +08001280
Patrick Venture0b02be92018-08-31 11:55:55 -07001281std::map<Mode::Modes, IpmiValue> modeDbusToIpmi = {
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001282 {Mode::Modes::Safe, 0x03},
1283 {Mode::Modes::Setup, 0x06},
Patrick Venture0b02be92018-08-31 11:55:55 -07001284 {Mode::Modes::Regular, ipmiDefault}};
shgoupfd84fbbf2015-12-17 10:05:51 +08001285
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001286} // namespace boot_options
shgoupfd84fbbf2015-12-17 10:05:51 +08001287
Marri Devender Rao81719702018-05-07 00:53:48 -05001288/** @brief Set the property value for boot source
1289 * @param[in] source - boot source value
1290 * @return On failure return IPMI error.
1291 */
1292static ipmi_ret_t setBootSource(const Source::Sources& source)
1293{
1294 using namespace chassis::internal;
1295 using namespace chassis::internal::cache;
1296 sdbusplus::message::variant<std::string> property =
1297 convertForMessage(source);
1298 auto bootSetting = settings::boot::setting(objects, bootSourceIntf);
1299 const auto& bootSourceSetting = std::get<settings::Path>(bootSetting);
Patrick Venture0b02be92018-08-31 11:55:55 -07001300 auto method = dbus.new_method_call(
1301 objects.service(bootSourceSetting, bootSourceIntf).c_str(),
1302 bootSourceSetting.c_str(), ipmi::PROP_INTF, "Set");
Marri Devender Rao81719702018-05-07 00:53:48 -05001303 method.append(bootSourceIntf, "BootSource", property);
1304 auto reply = dbus.call(method);
1305 if (reply.is_method_error())
1306 {
1307 log<level::ERR>("Error in BootSource Set");
1308 report<InternalFailure>();
1309 return IPMI_CC_UNSPECIFIED_ERROR;
1310 }
1311 return IPMI_CC_OK;
1312}
1313
Patrick Venture0b02be92018-08-31 11:55:55 -07001314/** @brief Set the property value for boot mode
Marri Devender Rao81719702018-05-07 00:53:48 -05001315 * @param[in] mode - boot mode value
1316 * @return On failure return IPMI error.
1317 */
1318static ipmi_ret_t setBootMode(const Mode::Modes& mode)
1319{
1320 using namespace chassis::internal;
1321 using namespace chassis::internal::cache;
Patrick Venture0b02be92018-08-31 11:55:55 -07001322 sdbusplus::message::variant<std::string> property = convertForMessage(mode);
Marri Devender Rao81719702018-05-07 00:53:48 -05001323 auto bootSetting = settings::boot::setting(objects, bootModeIntf);
1324 const auto& bootModeSetting = std::get<settings::Path>(bootSetting);
Patrick Venture0b02be92018-08-31 11:55:55 -07001325 auto method = dbus.new_method_call(
1326 objects.service(bootModeSetting, bootModeIntf).c_str(),
1327 bootModeSetting.c_str(), ipmi::PROP_INTF, "Set");
Marri Devender Rao81719702018-05-07 00:53:48 -05001328 method.append(bootModeIntf, "BootMode", property);
1329 auto reply = dbus.call(method);
1330 if (reply.is_method_error())
1331 {
1332 log<level::ERR>("Error in BootMode Set");
1333 report<InternalFailure>();
1334 return IPMI_CC_UNSPECIFIED_ERROR;
1335 }
1336 return IPMI_CC_OK;
1337}
1338
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001339ipmi_ret_t ipmi_chassis_get_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1340 ipmi_request_t request,
1341 ipmi_response_t response,
1342 ipmi_data_len_t data_len,
1343 ipmi_context_t context)
Adriana Kobylak40814c62015-10-27 15:58:44 -05001344{
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001345 using namespace boot_options;
shgoupfd84fbbf2015-12-17 10:05:51 +08001346 ipmi_ret_t rc = IPMI_CC_PARM_NOT_SUPPORTED;
Patrick Venture0b02be92018-08-31 11:55:55 -07001347 char* p = NULL;
1348 get_sys_boot_options_response_t* resp =
1349 (get_sys_boot_options_response_t*)response;
1350 get_sys_boot_options_t* reqptr = (get_sys_boot_options_t*)request;
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001351 IpmiValue bootOption = ipmiDefault;
Adriana Kobylak40814c62015-10-27 15:58:44 -05001352
Patrick Ventureb51bf9c2018-09-10 15:53:14 -07001353 std::memset(resp, 0, sizeof(*resp));
Patrick Venture0b02be92018-08-31 11:55:55 -07001354 resp->version = SET_PARM_VERSION;
1355 resp->parm = 5;
1356 resp->data[0] = SET_PARM_BOOT_FLAGS_VALID_ONE_TIME;
Adriana Kobylak40814c62015-10-27 15:58:44 -05001357
shgoupfd84fbbf2015-12-17 10:05:51 +08001358 /*
1359 * Parameter #5 means boot flags. Please refer to 28.13 of ipmi doc.
1360 * This is the only parameter used by petitboot.
1361 */
Patrick Venture0b02be92018-08-31 11:55:55 -07001362 if (reqptr->parameter ==
1363 static_cast<uint8_t>(BootOptionParameter::BOOT_FLAGS))
1364 {
shgoupfd84fbbf2015-12-17 10:05:51 +08001365
Ratan Guptafd28dd72016-08-01 04:58:01 -05001366 *data_len = static_cast<uint8_t>(BootOptionResponseSize::BOOT_FLAGS);
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001367 using namespace chassis::internal;
1368 using namespace chassis::internal::cache;
shgoupfd84fbbf2015-12-17 10:05:51 +08001369
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001370 try
ratagupta6f6bff2016-04-04 06:20:11 -05001371 {
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001372 auto bootSetting = settings::boot::setting(objects, bootSourceIntf);
1373 const auto& bootSourceSetting =
1374 std::get<settings::Path>(bootSetting);
1375 auto oneTimeEnabled =
1376 std::get<settings::boot::OneTimeEnabled>(bootSetting);
Patrick Venture0b02be92018-08-31 11:55:55 -07001377 auto method = dbus.new_method_call(
1378 objects.service(bootSourceSetting, bootSourceIntf).c_str(),
1379 bootSourceSetting.c_str(), ipmi::PROP_INTF, "Get");
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001380 method.append(bootSourceIntf, "BootSource");
1381 auto reply = dbus.call(method);
1382 if (reply.is_method_error())
1383 {
1384 log<level::ERR>("Error in BootSource Get");
1385 report<InternalFailure>();
1386 *data_len = 0;
1387 return IPMI_CC_UNSPECIFIED_ERROR;
1388 }
1389 sdbusplus::message::variant<std::string> result;
1390 reply.read(result);
William A. Kennington III4c008022018-10-12 17:18:14 -07001391 auto bootSource = Source::convertSourcesFromString(
1392 variant_ns::get<std::string>(result));
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001393
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001394 bootSetting = settings::boot::setting(objects, bootModeIntf);
1395 const auto& bootModeSetting = std::get<settings::Path>(bootSetting);
1396 method = dbus.new_method_call(
Patrick Venture0b02be92018-08-31 11:55:55 -07001397 objects.service(bootModeSetting, bootModeIntf).c_str(),
1398 bootModeSetting.c_str(), ipmi::PROP_INTF, "Get");
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001399 method.append(bootModeIntf, "BootMode");
1400 reply = dbus.call(method);
1401 if (reply.is_method_error())
1402 {
1403 log<level::ERR>("Error in BootMode Get");
1404 report<InternalFailure>();
1405 *data_len = 0;
1406 return IPMI_CC_UNSPECIFIED_ERROR;
1407 }
1408 reply.read(result);
William A. Kennington III4c008022018-10-12 17:18:14 -07001409 auto bootMode = Mode::convertModesFromString(
1410 variant_ns::get<std::string>(result));
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001411
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001412 bootOption = sourceDbusToIpmi.at(bootSource);
1413 if ((Mode::Modes::Regular == bootMode) &&
1414 (Source::Sources::Default == bootSource))
1415 {
1416 bootOption = ipmiDefault;
1417 }
1418 else if (Source::Sources::Default == bootSource)
1419 {
1420 bootOption = modeDbusToIpmi.at(bootMode);
1421 }
1422 resp->data[1] = (bootOption << 2);
ratagupta6f6bff2016-04-04 06:20:11 -05001423
Patrick Venture0b02be92018-08-31 11:55:55 -07001424 resp->data[0] = oneTimeEnabled
1425 ? SET_PARM_BOOT_FLAGS_VALID_ONE_TIME
1426 : SET_PARM_BOOT_FLAGS_VALID_PERMANENT;
ratagupta6f6bff2016-04-04 06:20:11 -05001427
ratagupta6f6bff2016-04-04 06:20:11 -05001428 rc = IPMI_CC_OK;
ratagupta6f6bff2016-04-04 06:20:11 -05001429 }
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001430 catch (InternalFailure& e)
1431 {
1432 report<InternalFailure>();
1433 *data_len = 0;
1434 return IPMI_CC_UNSPECIFIED_ERROR;
1435 }
Patrick Venture0b02be92018-08-31 11:55:55 -07001436 }
1437 else if (reqptr->parameter ==
1438 static_cast<uint8_t>(BootOptionParameter::OPAL_NETWORK_SETTINGS))
1439 {
Ratan Guptafd28dd72016-08-01 04:58:01 -05001440
Patrick Venture0b02be92018-08-31 11:55:55 -07001441 *data_len =
1442 static_cast<uint8_t>(BootOptionResponseSize::OPAL_NETWORK_SETTINGS);
Ratan Guptafd28dd72016-08-01 04:58:01 -05001443
Patrick Venture0b02be92018-08-31 11:55:55 -07001444 resp->parm =
1445 static_cast<uint8_t>(BootOptionParameter::OPAL_NETWORK_SETTINGS);
Ratan Guptafd28dd72016-08-01 04:58:01 -05001446
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001447 int ret = getHostNetworkData(resp);
Ratan Guptafd28dd72016-08-01 04:58:01 -05001448
Patrick Venture0b02be92018-08-31 11:55:55 -07001449 if (ret < 0)
1450 {
Ratan Guptafd28dd72016-08-01 04:58:01 -05001451
Aditya Saripalli5fb14602017-11-09 14:46:27 +05301452 log<level::ERR>(
Patrick Venture0b02be92018-08-31 11:55:55 -07001453 "getHostNetworkData failed for get_sys_boot_options.");
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001454 rc = IPMI_CC_UNSPECIFIED_ERROR;
Patrick Venture0b02be92018-08-31 11:55:55 -07001455 }
1456 else
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001457 rc = IPMI_CC_OK;
Ratan Guptafd28dd72016-08-01 04:58:01 -05001458 }
1459
Patrick Venture0b02be92018-08-31 11:55:55 -07001460 else
1461 {
1462 log<level::ERR>("Unsupported parameter",
1463 entry("PARAM=0x%x", reqptr->parameter));
shgoupfd84fbbf2015-12-17 10:05:51 +08001464 }
1465
1466 if (p)
1467 free(p);
1468
Ratan Guptafd28dd72016-08-01 04:58:01 -05001469 if (rc == IPMI_CC_OK)
1470 {
1471 *data_len += 2;
1472 }
1473
shgoupfd84fbbf2015-12-17 10:05:51 +08001474 return rc;
1475}
1476
shgoupfd84fbbf2015-12-17 10:05:51 +08001477ipmi_ret_t ipmi_chassis_set_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001478 ipmi_request_t request,
1479 ipmi_response_t response,
1480 ipmi_data_len_t data_len,
1481 ipmi_context_t context)
shgoupfd84fbbf2015-12-17 10:05:51 +08001482{
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001483 using namespace boot_options;
shgoupfd84fbbf2015-12-17 10:05:51 +08001484 ipmi_ret_t rc = IPMI_CC_OK;
Patrick Venture0b02be92018-08-31 11:55:55 -07001485 set_sys_boot_options_t* reqptr = (set_sys_boot_options_t*)request;
shgoupfd84fbbf2015-12-17 10:05:51 +08001486
Patrick Ventureb51bf9c2018-09-10 15:53:14 -07001487 std::printf("IPMI SET_SYS_BOOT_OPTIONS reqptr->parameter =[%d]\n",
1488 reqptr->parameter);
Ratan Guptafd28dd72016-08-01 04:58:01 -05001489
shgoupfd84fbbf2015-12-17 10:05:51 +08001490 // This IPMI command does not have any resposne data
1491 *data_len = 0;
1492
1493 /* 000101
1494 * Parameter #5 means boot flags. Please refer to 28.13 of ipmi doc.
1495 * This is the only parameter used by petitboot.
1496 */
Ratan Guptafd28dd72016-08-01 04:58:01 -05001497
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001498 if (reqptr->parameter == (uint8_t)BootOptionParameter::BOOT_FLAGS)
1499 {
1500 IpmiValue bootOption = ((reqptr->data[1] & 0x3C) >> 2);
1501 using namespace chassis::internal;
1502 using namespace chassis::internal::cache;
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001503 auto oneTimeEnabled = false;
1504 constexpr auto enabledIntf = "xyz.openbmc_project.Object.Enable";
Tom Joseph57e8eb72017-09-25 18:05:02 +05301505 constexpr auto oneTimePath =
Patrick Venture0b02be92018-08-31 11:55:55 -07001506 "/xyz/openbmc_project/control/host0/boot/one_time";
shgoupfd84fbbf2015-12-17 10:05:51 +08001507
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001508 try
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001509 {
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001510 bool permanent =
1511 (reqptr->data[0] & SET_PARM_BOOT_FLAGS_PERMANENT) ==
1512 SET_PARM_BOOT_FLAGS_PERMANENT;
1513
Patrick Venture0b02be92018-08-31 11:55:55 -07001514 auto bootSetting = settings::boot::setting(objects, bootSourceIntf);
Tom Joseph57e8eb72017-09-25 18:05:02 +05301515
1516 oneTimeEnabled =
1517 std::get<settings::boot::OneTimeEnabled>(bootSetting);
1518
1519 /*
1520 * Check if the current boot setting is onetime or permanent, if the
1521 * request in the command is otherwise, then set the "Enabled"
1522 * property in one_time object path to 'True' to indicate onetime
1523 * and 'False' to indicate permanent.
1524 *
1525 * Once the onetime/permanent setting is applied, then the bootMode
1526 * and bootSource is updated for the corresponding object.
1527 */
1528 if ((permanent && oneTimeEnabled) ||
1529 (!permanent && !oneTimeEnabled))
1530 {
1531 auto service = ipmi::getService(dbus, enabledIntf, oneTimePath);
1532
Patrick Venture0b02be92018-08-31 11:55:55 -07001533 ipmi::setDbusProperty(dbus, service, oneTimePath, enabledIntf,
1534 "Enabled", !permanent);
Tom Joseph57e8eb72017-09-25 18:05:02 +05301535 }
1536
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001537 auto modeItr = modeIpmiToDbus.find(bootOption);
1538 auto sourceItr = sourceIpmiToDbus.find(bootOption);
1539 if (sourceIpmiToDbus.end() != sourceItr)
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001540 {
Marri Devender Rao81719702018-05-07 00:53:48 -05001541 rc = setBootSource(sourceItr->second);
1542 if (rc != IPMI_CC_OK)
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001543 {
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001544 *data_len = 0;
Marri Devender Rao81719702018-05-07 00:53:48 -05001545 return rc;
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001546 }
Marri Devender Rao54fa1302018-05-07 01:06:23 -05001547 // If a set boot device is mapping to a boot source, then reset
1548 // the boot mode D-Bus property to default.
1549 // This way the ipmid code can determine which property is not
1550 // at the default value
Patrick Venture0b02be92018-08-31 11:55:55 -07001551 if (sourceItr->second != Source::Sources::Default)
Marri Devender Rao54fa1302018-05-07 01:06:23 -05001552 {
1553 setBootMode(Mode::Modes::Regular);
1554 }
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001555 }
1556 if (modeIpmiToDbus.end() != modeItr)
1557 {
Marri Devender Rao81719702018-05-07 00:53:48 -05001558 rc = setBootMode(modeItr->second);
1559 if (rc != IPMI_CC_OK)
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001560 {
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001561 *data_len = 0;
Marri Devender Rao81719702018-05-07 00:53:48 -05001562 return rc;
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001563 }
Marri Devender Rao54fa1302018-05-07 01:06:23 -05001564 // If a set boot device is mapping to a boot mode, then reset
1565 // the boot source D-Bus property to default.
1566 // This way the ipmid code can determine which property is not
1567 // at the default value
Patrick Venture0b02be92018-08-31 11:55:55 -07001568 if (modeItr->second != Mode::Modes::Regular)
Marri Devender Rao54fa1302018-05-07 01:06:23 -05001569 {
1570 setBootSource(Source::Sources::Default);
1571 }
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001572 }
1573 }
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001574 catch (InternalFailure& e)
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001575 {
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001576 report<InternalFailure>();
1577 *data_len = 0;
1578 return IPMI_CC_UNSPECIFIED_ERROR;
shgoupfd84fbbf2015-12-17 10:05:51 +08001579 }
Patrick Venture0b02be92018-08-31 11:55:55 -07001580 }
1581 else if (reqptr->parameter ==
1582 (uint8_t)BootOptionParameter::OPAL_NETWORK_SETTINGS)
1583 {
Ratan Guptafd28dd72016-08-01 04:58:01 -05001584
1585 int ret = setHostNetworkData(reqptr);
Patrick Venture0b02be92018-08-31 11:55:55 -07001586 if (ret < 0)
1587 {
Aditya Saripalli5fb14602017-11-09 14:46:27 +05301588 log<level::ERR>(
Patrick Venture0b02be92018-08-31 11:55:55 -07001589 "setHostNetworkData failed for set_sys_boot_options");
Ratan Guptafd28dd72016-08-01 04:58:01 -05001590 rc = IPMI_CC_UNSPECIFIED_ERROR;
1591 }
Patrick Venture0b02be92018-08-31 11:55:55 -07001592 }
1593 else if (reqptr->parameter ==
1594 static_cast<uint8_t>(BootOptionParameter::BOOT_INFO))
1595 {
Tom Josephf536c902017-09-25 18:08:15 +05301596 // Handle parameter #4 and return command completed normally
1597 // (IPMI_CC_OK). There is no implementation in OpenBMC for this
1598 // parameter. This is added to support the ipmitool command `chassis
1599 // bootdev` which sends set on parameter #4, before setting the boot
1600 // flags.
1601 rc = IPMI_CC_OK;
Patrick Venture0b02be92018-08-31 11:55:55 -07001602 }
1603 else
1604 {
1605 log<level::ERR>("Unsupported parameter",
1606 entry("PARAM=0x%x", reqptr->parameter));
shgoupfd84fbbf2015-12-17 10:05:51 +08001607 rc = IPMI_CC_PARM_NOT_SUPPORTED;
Adriana Kobylak40814c62015-10-27 15:58:44 -05001608 }
1609
1610 return rc;
1611}
1612
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -05001613ipmi_ret_t ipmiGetPOHCounter(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1614 ipmi_request_t request, ipmi_response_t response,
1615 ipmi_data_len_t data_len, ipmi_context_t context)
1616{
1617 // sd_bus error
1618 ipmi_ret_t rc = IPMI_CC_OK;
1619
1620 auto resptr = reinterpret_cast<GetPOHCountResponse*>(response);
1621
1622 try
1623 {
1624 auto pohCounter = getPOHCounter();
1625 resptr->counterReading[0] = pohCounter;
1626 resptr->counterReading[1] = pohCounter >> 8;
1627 resptr->counterReading[2] = pohCounter >> 16;
1628 resptr->counterReading[3] = pohCounter >> 24;
1629 }
1630 catch (std::exception& e)
1631 {
1632 log<level::ERR>(e.what());
1633 return IPMI_CC_UNSPECIFIED_ERROR;
1634 }
1635
1636 resptr->minPerCount = poh::minutesPerCount;
1637 *data_len = sizeof(GetPOHCountResponse);
1638
1639 return rc;
1640}
1641
Yong Lic6713cf2018-09-12 12:35:13 +08001642ipmi_ret_t ipmi_chassis_set_power_restore_policy(
1643 ipmi_netfn_t netfn, ipmi_cmd_t cmd, ipmi_request_t request,
1644 ipmi_response_t response, ipmi_data_len_t data_len, ipmi_context_t context)
1645{
1646 auto* reqptr = reinterpret_cast<uint8_t*>(request);
1647 auto* resptr = reinterpret_cast<uint8_t*>(response);
1648 uint8_t reqPolicy = 0;
1649
1650 power_policy::DbusValue value =
1651 power_policy::RestorePolicy::Policy::AlwaysOff;
1652
1653 if (*data_len != power_policy::setPolicyReqLen)
1654 {
1655 phosphor::logging::log<level::ERR>("Unsupported request length",
1656 entry("LEN=0x%x", *data_len));
1657 *data_len = 0;
1658 return IPMI_CC_REQ_DATA_LEN_INVALID;
1659 }
1660
1661 reqPolicy = *reqptr & power_policy::policyBitMask;
1662 if (reqPolicy > power_policy::noChange)
1663 {
1664 phosphor::logging::log<level::ERR>("Reserved request parameter",
1665 entry("REQ=0x%x", reqPolicy));
1666 *data_len = 0;
1667 return IPMI_CC_PARM_NOT_SUPPORTED;
1668 }
1669
1670 if (reqPolicy == power_policy::noChange)
1671 {
1672 // just return the supported policy
1673 *resptr = power_policy::allSupport;
1674 *data_len = power_policy::setPolicyReqLen;
1675 return IPMI_CC_OK;
1676 }
1677
1678 for (auto const& it : power_policy::dbusToIpmi)
1679 {
1680 if (it.second == reqPolicy)
1681 {
1682 value = it.first;
1683 break;
1684 }
1685 }
1686
1687 try
1688 {
1689 const settings::Path& powerRestoreSetting =
1690 chassis::internal::cache::objects.map
1691 .at(chassis::internal::powerRestoreIntf)
1692 .front();
1693 sdbusplus::message::variant<std::string> property =
1694 convertForMessage(value);
1695
1696 auto method = chassis::internal::dbus.new_method_call(
1697 chassis::internal::cache::objects
1698 .service(powerRestoreSetting,
1699 chassis::internal::powerRestoreIntf)
1700 .c_str(),
1701 powerRestoreSetting.c_str(), ipmi::PROP_INTF, "Set");
1702
1703 method.append(chassis::internal::powerRestoreIntf, "PowerRestorePolicy",
1704 property);
1705 auto reply = chassis::internal::dbus.call(method);
1706 if (reply.is_method_error())
1707 {
1708 phosphor::logging::log<level::ERR>("Unspecified Error");
1709 *data_len = 0;
1710 return IPMI_CC_UNSPECIFIED_ERROR;
1711 }
1712 }
1713 catch (InternalFailure& e)
1714 {
1715 report<InternalFailure>();
1716 *data_len = 0;
1717 return IPMI_CC_UNSPECIFIED_ERROR;
1718 }
1719
1720 *data_len = power_policy::setPolicyReqLen;
1721 return IPMI_CC_OK;
1722}
1723
Adriana Kobylak40814c62015-10-27 15:58:44 -05001724void register_netfn_chassis_functions()
1725{
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001726 createIdentifyTimer();
1727
Tom05732372016-09-06 17:21:23 +05301728 // <Wildcard Command>
Patrick Venture0b02be92018-08-31 11:55:55 -07001729 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_WILDCARD, NULL,
1730 ipmi_chassis_wildcard, PRIVILEGE_USER);
Adriana Kobylak40814c62015-10-27 15:58:44 -05001731
Tom05732372016-09-06 17:21:23 +05301732 // Get Chassis Capabilities
Patrick Venture0b02be92018-08-31 11:55:55 -07001733 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_GET_CHASSIS_CAP, NULL,
1734 ipmi_get_chassis_cap, PRIVILEGE_USER);
Nan Li8d15fb42016-08-16 22:29:40 +08001735
Yong Liae4b0402018-11-02 11:12:14 +08001736 // Set Chassis Capabilities
1737 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_SET_CHASSIS_CAP, NULL,
1738 ipmi_set_chassis_cap, PRIVILEGE_USER);
1739
Tom05732372016-09-06 17:21:23 +05301740 // <Get System Boot Options>
Tom05732372016-09-06 17:21:23 +05301741 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_GET_SYS_BOOT_OPTIONS, NULL,
Patrick Venture0b02be92018-08-31 11:55:55 -07001742 ipmi_chassis_get_sys_boot_options,
1743 PRIVILEGE_OPERATOR);
Adriana Kobylak40814c62015-10-27 15:58:44 -05001744
Tom05732372016-09-06 17:21:23 +05301745 // <Get Chassis Status>
Patrick Venture0b02be92018-08-31 11:55:55 -07001746 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_CHASSIS_STATUS, NULL,
1747 ipmi_get_chassis_status, PRIVILEGE_USER);
Nan Lifdd8ec52016-08-28 03:57:40 +08001748
Tom05732372016-09-06 17:21:23 +05301749 // <Chassis Control>
Patrick Venture0b02be92018-08-31 11:55:55 -07001750 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_CHASSIS_CONTROL, NULL,
1751 ipmi_chassis_control, PRIVILEGE_OPERATOR);
shgoupfd84fbbf2015-12-17 10:05:51 +08001752
Tom Joseph5110c122018-03-23 17:55:40 +05301753 // <Chassis Identify>
Tom Joseph5110c122018-03-23 17:55:40 +05301754 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_CHASSIS_IDENTIFY, NULL,
1755 ipmi_chassis_identify, PRIVILEGE_OPERATOR);
1756
Tom05732372016-09-06 17:21:23 +05301757 // <Set System Boot Options>
Tom05732372016-09-06 17:21:23 +05301758 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_SET_SYS_BOOT_OPTIONS, NULL,
Patrick Venture0b02be92018-08-31 11:55:55 -07001759 ipmi_chassis_set_sys_boot_options,
1760 PRIVILEGE_OPERATOR);
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -05001761 // <Get POH Counter>
1762 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_GET_POH_COUNTER, NULL,
1763 ipmiGetPOHCounter, PRIVILEGE_USER);
Yong Lic6713cf2018-09-12 12:35:13 +08001764
1765 // <Set Power Restore Policy>
1766 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_SET_RESTORE_POLICY, NULL,
1767 ipmi_chassis_set_power_restore_policy,
1768 PRIVILEGE_OPERATOR);
vishwa36993272015-11-20 12:43:49 -06001769}