blob: 6c233507c1a5f1dd1035b567a09226021eaf1161 [file] [log] [blame]
Adriana Kobylak40814c62015-10-27 15:58:44 -05001#include "chassishandler.h"
Patrick Williams37af7332016-09-02 21:21:42 -05002#include "host-ipmid/ipmid-api.h"
Adriana Kobylak40814c62015-10-27 15:58:44 -05003#include <stdio.h>
Ratan Guptafd28dd72016-08-01 04:58:01 -05004#include <stdlib.h>
Adriana Kobylak40814c62015-10-27 15:58:44 -05005#include <stdint.h>
Brad Bishop35518682016-07-22 08:35:41 -04006#include <mapper.h>
Ratan Guptafd28dd72016-08-01 04:58:01 -05007#include <arpa/inet.h>
8#include <netinet/in.h>
9#include <limits.h>
10#include <string.h>
11#include <endian.h>
12#include <sstream>
13#include <array>
Andrew Geisslera6e3a302017-05-31 19:34:00 -050014#include <fstream>
15#include <experimental/filesystem>
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +053016#include <phosphor-logging/log.hpp>
17#include <xyz/openbmc_project/State/Host/server.hpp>
Vishwanatha Subbannab891a572017-03-31 11:34:48 +053018#include "config.h"
ratagupta6f6bff2016-04-04 06:20:11 -050019
20//Defines
Ratan Guptafd28dd72016-08-01 04:58:01 -050021#define SET_PARM_VERSION 0x01
22#define SET_PARM_BOOT_FLAGS_PERMANENT 0x40 //boot flags data1 7th bit on
ratagupta6f6bff2016-04-04 06:20:11 -050023#define SET_PARM_BOOT_FLAGS_VALID_ONE_TIME 0x80 //boot flags data1 8th bit on
Ratan Guptafd28dd72016-08-01 04:58:01 -050024#define SET_PARM_BOOT_FLAGS_VALID_PERMANENT 0xC0 //boot flags data1 7 & 8 bit on
ratagupta6f6bff2016-04-04 06:20:11 -050025
Ratan Guptafd28dd72016-08-01 04:58:01 -050026constexpr size_t SIZE_MAC = 18;
27constexpr size_t SIZE_BOOT_OPTION = (uint8_t)BootOptionResponseSize::
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -050028 OPAL_NETWORK_SETTINGS;//Maximum size of the boot option parametrs
Ratan Guptafd28dd72016-08-01 04:58:01 -050029constexpr size_t SIZE_PREFIX = 7;
30constexpr size_t MAX_PREFIX_VALUE = 32;
31constexpr size_t SIZE_COOKIE = 4;
32constexpr size_t SIZE_VERSION = 2;
33constexpr auto MAC_ADDRESS_FORMAT = "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx";
34constexpr auto IP_ADDRESS_FORMAT = "%d.%d.%d.%d";
Matthew Barth8b470052016-09-21 10:02:57 -050035constexpr auto PREFIX_FORMAT = "%hhd";
Ratan Guptafd28dd72016-08-01 04:58:01 -050036constexpr auto ADDR_TYPE_FORMAT = "%hhx";
37//PetiBoot-Specific
38static constexpr uint8_t net_conf_initial_bytes[] = {0x80,0x21, 0x70 ,0x62 ,0x21,
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -050039 0x00 ,0x01 ,0x06 ,0x04};
Ratan Guptafd28dd72016-08-01 04:58:01 -050040
41static constexpr size_t COOKIE_OFFSET = 1;
42static constexpr size_t VERSION_OFFSET = 5;
43static constexpr size_t MAC_OFFSET = 9;
44static constexpr size_t ADDRTYPE_OFFSET = 16;
45static constexpr size_t IPADDR_OFFSET = 17;
46static constexpr size_t PREFIX_OFFSET = 21;
47static constexpr size_t GATEWAY_OFFSET = 22;
ratagupta6f6bff2016-04-04 06:20:11 -050048
Andrew Geisslera6e3a302017-05-31 19:34:00 -050049using namespace phosphor::logging;
vishwa36993272015-11-20 12:43:49 -060050
shgoupfd84fbbf2015-12-17 10:05:51 +080051
Adriana Kobylak40814c62015-10-27 15:58:44 -050052void register_netfn_chassis_functions() __attribute__((constructor));
53
shgoupfd84fbbf2015-12-17 10:05:51 +080054// Host settings in dbus
55// Service name should be referenced by connection name got via object mapper
56const char *settings_object_name = "/org/openbmc/settings/host0";
57const char *settings_intf_name = "org.freedesktop.DBus.Properties";
58const char *host_intf_name = "org.openbmc.settings.Host";
59
Nan Li8d15fb42016-08-16 22:29:40 +080060typedef struct
61{
62 uint8_t cap_flags;
63 uint8_t fru_info_dev_addr;
64 uint8_t sdr_dev_addr;
65 uint8_t sel_dev_addr;
66 uint8_t system_management_dev_addr;
67 uint8_t bridge_dev_addr;
68}__attribute__((packed)) ipmi_chassis_cap_t;
69
Nan Lifdd8ec52016-08-28 03:57:40 +080070typedef struct
71{
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -050072 uint8_t cur_power_state;
73 uint8_t last_power_event;
74 uint8_t misc_power_state;
75 uint8_t front_panel_button_cap_status;
Nan Lifdd8ec52016-08-28 03:57:40 +080076}__attribute__((packed)) ipmi_get_chassis_status_t;
77
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +053078// Phosphor Host State manager
79namespace State = sdbusplus::xyz::openbmc_project::State::server;
80
Andrew Geisslera6e3a302017-05-31 19:34:00 -050081namespace fs = std::experimental::filesystem;
82
ratagupta6f6bff2016-04-04 06:20:11 -050083int dbus_get_property(const char *name, char **buf)
shgoupfd84fbbf2015-12-17 10:05:51 +080084{
85 sd_bus_error error = SD_BUS_ERROR_NULL;
86 sd_bus_message *m = NULL;
87 sd_bus *bus = NULL;
88 char *temp_buf = NULL;
89 char *connection = NULL;
90 int r;
91
Brad Bishop35518682016-07-22 08:35:41 -040092 // Get the system bus where most system services are provided.
93 bus = ipmid_get_sd_bus_connection();
shgoupfd84fbbf2015-12-17 10:05:51 +080094
Brad Bishop35518682016-07-22 08:35:41 -040095 r = mapper_get_service(bus, settings_object_name, &connection);
shgoupfd84fbbf2015-12-17 10:05:51 +080096 if (r < 0) {
Brad Bishop819ddd42016-10-05 21:19:19 -040097 fprintf(stderr, "Failed to get %s connection: %s\n",
98 settings_object_name, strerror(-r));
shgoupfd84fbbf2015-12-17 10:05:51 +080099 goto finish;
100 }
101
shgoupfd84fbbf2015-12-17 10:05:51 +0800102 /*
103 * Bus, service, object path, interface and method are provided to call
104 * the method.
105 * Signatures and input arguments are provided by the arguments at the
106 * end.
107 */
108 r = sd_bus_call_method(bus,
109 connection, /* service to contact */
110 settings_object_name, /* object path */
111 settings_intf_name, /* interface name */
112 "Get", /* method name */
113 &error, /* object to return error in */
114 &m, /* return message on success */
115 "ss", /* input signature */
116 host_intf_name, /* first argument */
ratagupta6f6bff2016-04-04 06:20:11 -0500117 name); /* second argument */
shgoupfd84fbbf2015-12-17 10:05:51 +0800118
119 if (r < 0) {
120 fprintf(stderr, "Failed to issue method call: %s\n", error.message);
121 goto finish;
122 }
123
124 /*
125 * The output should be parsed exactly the same as the output formatting
126 * specified.
127 */
128 r = sd_bus_message_read(m, "v", "s", &temp_buf);
129 if (r < 0) {
130 fprintf(stderr, "Failed to parse response message: %s\n", strerror(-r));
131 goto finish;
132 }
133
Matthew Barth56181052017-01-23 09:36:29 -0600134 *buf = strdup(temp_buf);
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500135 /* *buf = (char*) malloc(strlen(temp_buf));
shgoupfd84fbbf2015-12-17 10:05:51 +0800136 if (*buf) {
137 strcpy(*buf, temp_buf);
138 }
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500139 */
shgoupfd84fbbf2015-12-17 10:05:51 +0800140 printf("IPMID boot option property get: {%s}.\n", (char *) temp_buf);
141
142finish:
143 sd_bus_error_free(&error);
144 sd_bus_message_unref(m);
145 free(connection);
146
147 return r;
148}
149
ratagupta6f6bff2016-04-04 06:20:11 -0500150int dbus_set_property(const char * name, const char *value)
shgoupfd84fbbf2015-12-17 10:05:51 +0800151{
152 sd_bus_error error = SD_BUS_ERROR_NULL;
153 sd_bus_message *m = NULL;
154 sd_bus *bus = NULL;
155 char *connection = NULL;
156 int r;
157
Brad Bishop35518682016-07-22 08:35:41 -0400158 // Get the system bus where most system services are provided.
159 bus = ipmid_get_sd_bus_connection();
shgoupfd84fbbf2015-12-17 10:05:51 +0800160
Brad Bishop35518682016-07-22 08:35:41 -0400161 r = mapper_get_service(bus, settings_object_name, &connection);
shgoupfd84fbbf2015-12-17 10:05:51 +0800162 if (r < 0) {
Brad Bishop819ddd42016-10-05 21:19:19 -0400163 fprintf(stderr, "Failed to get %s connection: %s\n",
164 settings_object_name, strerror(-r));
shgoupfd84fbbf2015-12-17 10:05:51 +0800165 goto finish;
166 }
167
shgoupfd84fbbf2015-12-17 10:05:51 +0800168 /*
169 * Bus, service, object path, interface and method are provided to call
170 * the method.
171 * Signatures and input arguments are provided by the arguments at the
172 * end.
173 */
174 r = sd_bus_call_method(bus,
175 connection, /* service to contact */
176 settings_object_name, /* object path */
177 settings_intf_name, /* interface name */
178 "Set", /* method name */
179 &error, /* object to return error in */
180 &m, /* return message on success */
181 "ssv", /* input signature */
182 host_intf_name, /* first argument */
ratagupta6f6bff2016-04-04 06:20:11 -0500183 name, /* second argument */
shgoupfd84fbbf2015-12-17 10:05:51 +0800184 "s", /* third argument */
ratagupta6f6bff2016-04-04 06:20:11 -0500185 value); /* fourth argument */
shgoupfd84fbbf2015-12-17 10:05:51 +0800186
187 if (r < 0) {
188 fprintf(stderr, "Failed to issue method call: %s\n", error.message);
189 goto finish;
190 }
191
ratagupta6f6bff2016-04-04 06:20:11 -0500192 printf("IPMID boot option property set: {%s}.\n", value);
shgoupfd84fbbf2015-12-17 10:05:51 +0800193
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500194 finish:
shgoupfd84fbbf2015-12-17 10:05:51 +0800195 sd_bus_error_free(&error);
196 sd_bus_message_unref(m);
197 free(connection);
198
199 return r;
200}
201
Adriana Kobylak40814c62015-10-27 15:58:44 -0500202struct get_sys_boot_options_t {
203 uint8_t parameter;
204 uint8_t set;
205 uint8_t block;
206} __attribute__ ((packed));
207
shgoupfd84fbbf2015-12-17 10:05:51 +0800208struct get_sys_boot_options_response_t {
209 uint8_t version;
210 uint8_t parm;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500211 uint8_t data[SIZE_BOOT_OPTION];
shgoupfd84fbbf2015-12-17 10:05:51 +0800212} __attribute__ ((packed));
213
214struct set_sys_boot_options_t {
215 uint8_t parameter;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500216 uint8_t data[SIZE_BOOT_OPTION];
shgoupfd84fbbf2015-12-17 10:05:51 +0800217} __attribute__ ((packed));
218
Ratan Guptafd28dd72016-08-01 04:58:01 -0500219struct host_network_config_t {
220 std::string ipaddress;
221 std::string prefix;
222 std::string gateway;
223 std::string macaddress;
224 std::string addrType;
225
226 host_network_config_t()=default;
227};
228
229void fillNetworkConfig( host_network_config_t & host_config ,
230 const std::string& conf_str ) {
231
232 constexpr auto COMMA_DELIMITER = ",";
233 constexpr auto EQUAL_DELIMITER = "=";
234 size_t commaDelimtrPos = 0;
235 size_t equalDelimtrPos = 0,commaDelimtrPrevPos = 0;
236 std::string value;
237 while ( commaDelimtrPos < conf_str.length() ) {
238
239 commaDelimtrPos = conf_str.find(COMMA_DELIMITER,commaDelimtrPos);
240 //This condition is to extract the last
241 //Substring as we will not be having the delimeter
242 //at end. std::string::npos is -1
243
244 if ( commaDelimtrPos == std::string::npos ) {
245 commaDelimtrPos = conf_str.length();
246 }
247
248 equalDelimtrPos = conf_str.find (EQUAL_DELIMITER,commaDelimtrPrevPos);
249
250 //foo,ipaddress=1234
251 if ( equalDelimtrPos == std::string::npos ) {
252
253 commaDelimtrPos++;
254 commaDelimtrPrevPos= commaDelimtrPos;
255 continue;
256 }
257
258 value = conf_str.substr((equalDelimtrPos+1),
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500259 commaDelimtrPos-(equalDelimtrPos+1));
Ratan Guptafd28dd72016-08-01 04:58:01 -0500260
261#ifdef _IPMI_DEBUG_
262 printf ("Name=[%s],Value=[%s],commaDelimtrPos=[%d],\
263 commaDelimtrPrevPos=[%d],equalDelimtrPos=[%d]\n",
264 name.c_str(),value.c_str(),commaDelimtrPos,
265 commaDelimtrPrevPos,equalDelimtrPos);
266#endif
267
268 if ( 0 == conf_str.compare(commaDelimtrPrevPos,
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500269 equalDelimtrPos-commaDelimtrPrevPos,
270 "ipaddress" )) {
271 host_config.ipaddress = std::move(value);
Ratan Guptafd28dd72016-08-01 04:58:01 -0500272 }
273 else if ( 0 == conf_str.compare(commaDelimtrPrevPos,
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500274 equalDelimtrPos-commaDelimtrPrevPos,
275 "prefix" )) {
276 host_config.prefix = std::move(value);
Ratan Guptafd28dd72016-08-01 04:58:01 -0500277 }
278 else if ( 0 == conf_str.compare(commaDelimtrPrevPos,
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500279 equalDelimtrPos-commaDelimtrPrevPos,
280 "gateway" )) {
Ratan Guptafd28dd72016-08-01 04:58:01 -0500281 host_config.gateway = std::move(value);
282 }
283 else if ( 0 == conf_str.compare(commaDelimtrPrevPos,
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500284 equalDelimtrPos-commaDelimtrPrevPos,
285 "mac" )) {
Ratan Guptafd28dd72016-08-01 04:58:01 -0500286 host_config.macaddress = std::move(value);
287 }
288 else if ( 0 == conf_str.compare(commaDelimtrPrevPos,
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500289 equalDelimtrPos-commaDelimtrPrevPos,
290 "addr_type" )) {
Ratan Guptafd28dd72016-08-01 04:58:01 -0500291 host_config.addrType = std::move(value);
292 }
293
294 commaDelimtrPos++;
295 commaDelimtrPrevPos= commaDelimtrPos;
296 }
297}
298
299int getHostNetworkData(get_sys_boot_options_response_t* respptr)
300{
301
302 char *prop = nullptr;
303 int rc = dbus_get_property("network_config",&prop);
304
305 if ( rc < 0 ) {
306 fprintf(stderr, "Dbus get property(boot_flags) failed\
307 for get_sys_boot_options.\n");
308 return rc;
309 }
310
311 std::string conf_str(prop);
312
313 if ( prop ) {
314
315 free(prop);
316 prop = nullptr;
317 }
318
319 /* network_config property Value would be in the form of
320 * ipaddress=1.1.1.1,prefix=16,gateway=2.2.2.2,mac=11:22:33:44:55:66,dhcp=0
321 */
322
323 /* Parsing the string and fill the hostconfig structure with the
324 * values */
325
326 printf ("Configuration String[%s]\n ",conf_str.c_str());
327
328 host_network_config_t host_config;
329
330 // Fill the host_config from the configuration string
331 fillNetworkConfig(host_config,conf_str);
332
333 //Assigning the index as intialByteLength as it is fixed and prefilled.
334 printf ("host_config.macaddress.c_str()=[%s]\n",host_config.macaddress.c_str());
335 do{
336
337 rc = sscanf(host_config.macaddress.c_str(),MAC_ADDRESS_FORMAT,
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500338 (respptr->data+MAC_OFFSET), (respptr->data+MAC_OFFSET+1),
339 (respptr->data+MAC_OFFSET+2),(respptr->data+MAC_OFFSET+3),
340 (respptr->data+MAC_OFFSET+4), (respptr->data+MAC_OFFSET+5));
Ratan Guptafd28dd72016-08-01 04:58:01 -0500341
342
343 if ( rc < 6 ){
344 fprintf(stderr, "sscanf Failed in extracting mac address.\n");
345 rc = -1;
346 break;
347 }
348
349 //Conevrt the dhcp,ipaddress,mask and gateway as hex number
350 respptr->data[MAC_OFFSET+6]=0x00;
351
352 rc = sscanf(host_config.addrType.c_str(),ADDR_TYPE_FORMAT,
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500353 (respptr->data+ADDRTYPE_OFFSET));
Ratan Guptafd28dd72016-08-01 04:58:01 -0500354
355 if ( rc <= 0 ) {
356 fprintf(stderr, "sscanf Failed in extracting address type.\n");
357 rc = -1;
358 break;
359 }
360
361 //ipaddress and gateway would be in IPv4 format
362 rc = inet_pton(AF_INET,host_config.ipaddress.c_str(),
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500363 (respptr->data+IPADDR_OFFSET));
Ratan Guptafd28dd72016-08-01 04:58:01 -0500364
365 if ( rc <= 0 ) {
366 fprintf(stderr, "inet_pton failed during ipaddress coneversion\n");
367 rc = -1;
368 break;
369 }
370
371 rc = sscanf(host_config.prefix.c_str(),PREFIX_FORMAT,
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500372 (respptr->data+PREFIX_OFFSET));
Ratan Guptafd28dd72016-08-01 04:58:01 -0500373
374 if ( rc <= 0 ) {
375 fprintf(stderr, "sscanf failed during prefix extraction.\n");
376 rc = -1;
377 break;
378 }
379
380 rc = inet_pton(AF_INET,host_config.gateway.c_str(),
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500381 (respptr->data+GATEWAY_OFFSET));
Ratan Guptafd28dd72016-08-01 04:58:01 -0500382
383 if ( rc <= 0 ) {
384 fprintf(stderr, "inet_pton failed during gateway conversion.\n");
385 rc = -1;
386 break;
387 }
388
389 }while (0);
390
391 if ( rc ) {
392
393 //PetiBoot-Specific
394 //If sucess then copy the first 9 bytes to the data
395 //else set the respptr to 0
396
397 memcpy(respptr->data,net_conf_initial_bytes,
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500398 sizeof(net_conf_initial_bytes));
Ratan Guptafd28dd72016-08-01 04:58:01 -0500399
400#ifdef _IPMI_DEBUG_
401 printf ("\n===Printing the IPMI Formatted Data========\n");
402
403 for ( uint8_t pos = 0; pos<index; pos++ )
404 printf("%02x ", respptr->data[pos]);
405#endif
406
407 }else {
408
409 memset(respptr->data,0,SIZE_BOOT_OPTION);
410 }
411
412 return rc;
413}
414
415int setHostNetworkData(set_sys_boot_options_t * reqptr)
416{
417 std::string host_network_config;
418 char mac[SIZE_MAC] = {0};
419 char ipAddress[INET_ADDRSTRLEN] = {0};
420 char gateway[INET_ADDRSTRLEN] = {0};
421 char dhcp[SIZE_PREFIX] = {0};
422 char prefix[SIZE_PREFIX] = {0};
423 int rc = 0;
424 uint32_t zeroCookie=0;
425
426 //cookie starts from second byte
427 // version starts from sixth byte
428
429 do {
430
431 // cookie == 0x21 0x70 0x62 0x21
432 if ( memcmp(&(reqptr->data[COOKIE_OFFSET]),
433 (net_conf_initial_bytes+COOKIE_OFFSET),
434 SIZE_COOKIE) != 0 ) {
435 //cookie == 0
436 if ( memcmp(&(reqptr->data[COOKIE_OFFSET]),
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500437 &zeroCookie,
438 SIZE_COOKIE) == 0 ) {
Ratan Guptafd28dd72016-08-01 04:58:01 -0500439 rc = 0;
440 break;
441 }
442 //Invalid cookie
443 fprintf(stderr, "Invalid Cookie\n");
444 rc = -1;
445 break;
446 }
447 // vesion == 0x00 0x01
448 if ( memcmp(&(reqptr->data[VERSION_OFFSET]),
449 (net_conf_initial_bytes+VERSION_OFFSET),
450 SIZE_VERSION) != 0 ) {
451
452 fprintf(stderr, "Invalid Version\n");
453 rc = -1;
454 break;
455 }
456
457 snprintf(mac, SIZE_MAC, MAC_ADDRESS_FORMAT,
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500458 reqptr->data[MAC_OFFSET],
459 reqptr->data[MAC_OFFSET+1],
460 reqptr->data[MAC_OFFSET+2],
461 reqptr->data[MAC_OFFSET+3],
462 reqptr->data[MAC_OFFSET+4],
463 reqptr->data[MAC_OFFSET+5]);
Ratan Guptafd28dd72016-08-01 04:58:01 -0500464
465 snprintf(dhcp,SIZE_PREFIX, ADDR_TYPE_FORMAT, reqptr->data[ADDRTYPE_OFFSET]);
466 //Validating the address type which could be
467 //either static or dynamic
468 if( *(reqptr->data+ADDRTYPE_OFFSET) > 1 ) {
469
470 fprintf(stderr, "Invalid Address Type\n");
471 rc = -1;
472 break;
473
474 }
475
476 snprintf(ipAddress, INET_ADDRSTRLEN, IP_ADDRESS_FORMAT,
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500477 reqptr->data[IPADDR_OFFSET], reqptr->data[IPADDR_OFFSET+1],
478 reqptr->data[IPADDR_OFFSET+2], reqptr->data[IPADDR_OFFSET+3]);
Ratan Guptafd28dd72016-08-01 04:58:01 -0500479
480 //validating prefix
481 if ( *(reqptr->data+PREFIX_OFFSET) > (uint8_t)MAX_PREFIX_VALUE ) {
482
483 fprintf(stderr, "Invalid Prefix\n");
484 rc = -1;
485 break;
486 }
487
488 snprintf(prefix,SIZE_PREFIX,PREFIX_FORMAT, reqptr->data[PREFIX_OFFSET]);
489
490 snprintf(gateway, INET_ADDRSTRLEN,IP_ADDRESS_FORMAT,
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500491 reqptr->data[GATEWAY_OFFSET],
492 reqptr->data[GATEWAY_OFFSET+1],
493 reqptr->data[GATEWAY_OFFSET+2],
494 reqptr->data[GATEWAY_OFFSET+3]);
Ratan Guptafd28dd72016-08-01 04:58:01 -0500495
496
497 }while(0);
498
499 if( !rc )
500 {
501 //Cookie == 0 or it is a valid cookie
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500502 host_network_config += "ipaddress="+std::string(ipAddress)+",prefix="+
503 std::string(prefix)+",gateway="+std::string(gateway)+
504 ",mac="+std::string(mac)+",addr_type="+std::string(dhcp);
Ratan Guptafd28dd72016-08-01 04:58:01 -0500505
506 printf ("Network configuration changed: %s\n",host_network_config.c_str());
507
508 rc = dbus_set_property("network_config",host_network_config.c_str());
509
510 if ( rc < 0 ) {
511 fprintf(stderr, "Dbus set property(network_config)\
512 failed for set_sys_boot_options.\n");
513 rc = -1;
514 }
515
516 }
517 return rc;
518}
519
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500520ipmi_ret_t ipmi_chassis_wildcard(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
521 ipmi_request_t request,
522 ipmi_response_t response,
523 ipmi_data_len_t data_len,
524 ipmi_context_t context)
Adriana Kobylak40814c62015-10-27 15:58:44 -0500525{
526 printf("Handling CHASSIS WILDCARD Netfn:[0x%X], Cmd:[0x%X]\n",netfn, cmd);
527 // Status code.
Nan Li70aa8d92016-08-29 00:11:10 +0800528 ipmi_ret_t rc = IPMI_CC_INVALID;
Adriana Kobylak40814c62015-10-27 15:58:44 -0500529 *data_len = 0;
530 return rc;
531}
532
Nan Li8d15fb42016-08-16 22:29:40 +0800533ipmi_ret_t ipmi_get_chassis_cap(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500534 ipmi_request_t request, ipmi_response_t response,
535 ipmi_data_len_t data_len, ipmi_context_t context)
Nan Li8d15fb42016-08-16 22:29:40 +0800536{
537 // sd_bus error
538 ipmi_ret_t rc = IPMI_CC_OK;
539
540 ipmi_chassis_cap_t chassis_cap{};
541
542 *data_len = sizeof(ipmi_chassis_cap_t);
543
544 // TODO: need future work. Get those flag from MRW.
545
546 // capabilities flags
547 // [7..4] - reserved
548 // [3] – 1b = provides power interlock (IPM 1.5)
549 // [2] – 1b = provides Diagnostic Interrupt (FP NMI)
550 // [1] – 1b = provides “Front Panel Lockout” (indicates that the chassis has capabilities
551 // to lock out external power control and reset button or front panel interfaces
552 // and/or detect tampering with those interfaces).
553 // [0] -1b = Chassis provides intrusion (physical security) sensor.
554 // set to default value 0x0.
555 chassis_cap.cap_flags = 0x0;
556
557 // Since we do not have a separate SDR Device/SEL Device/ FRU repository.
558 // The 20h was given as those 5 device addresses.
559 // Chassis FRU info Device Address
560 chassis_cap.fru_info_dev_addr = 0x20;
561
562 // Chassis SDR Device Address
563 chassis_cap.sdr_dev_addr = 0x20;
564
565 // Chassis SEL Device Address
566 chassis_cap.sel_dev_addr = 0x20;
567
568 // Chassis System Management Device Address
569 chassis_cap.system_management_dev_addr = 0x20;
570
571 // Chassis Bridge Device Address.
572 chassis_cap.bridge_dev_addr = 0x20;
573
574 memcpy(response, &chassis_cap, *data_len);
575
576 return rc;
577}
578
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530579//------------------------------------------
580// Calls into Host State Manager Dbus object
581//------------------------------------------
582int initiate_state_transition(State::Host::Transition transition)
vishwa36993272015-11-20 12:43:49 -0600583{
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500584 // OpenBMC Host State Manager dbus framework
585 constexpr auto HOST_STATE_MANAGER_ROOT = "/xyz/openbmc_project/state/host0";
586 constexpr auto HOST_STATE_MANAGER_IFACE = "xyz.openbmc_project.State.Host";
587 constexpr auto DBUS_PROPERTY_IFACE = "org.freedesktop.DBus.Properties";
588 constexpr auto PROPERTY = "RequestedHostTransition";
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530589
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500590 // sd_bus error
591 int rc = 0;
592 char *busname = NULL;
vishwa36993272015-11-20 12:43:49 -0600593
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500594 // SD Bus error report mechanism.
595 sd_bus_error bus_error = SD_BUS_ERROR_NULL;
vishwa36993272015-11-20 12:43:49 -0600596
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500597 // Gets a hook onto either a SYSTEM or SESSION bus
598 sd_bus *bus_type = ipmid_get_sd_bus_connection();
599 rc = mapper_get_service(bus_type, HOST_STATE_MANAGER_ROOT, &busname);
600 if (rc < 0)
601 {
602 log<level::ERR>("Failed to get bus name",
603 entry("ERROR=%s, OBJPATH=%s",
604 strerror(-rc), HOST_STATE_MANAGER_ROOT));
605 return rc;
606 }
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530607
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500608 // Convert to string equivalent of the passed in transition enum.
609 auto request = State::convertForMessage(transition);
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530610
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500611 rc = sd_bus_call_method(bus_type, // On the system bus
612 busname, // Service to contact
613 HOST_STATE_MANAGER_ROOT, // Object path
614 DBUS_PROPERTY_IFACE, // Interface name
615 "Set", // Method to be called
616 &bus_error, // object to return error
617 nullptr, // Response buffer if any
618 "ssv", // Takes 3 arguments
619 HOST_STATE_MANAGER_IFACE,
620 PROPERTY,
621 "s", request.c_str());
622 if(rc < 0)
623 {
624 log<level::ERR>("Failed to initiate transition",
625 entry("ERROR=%s, REQUEST=%s",
626 bus_error.message, request.c_str()));
627 }
628 else
629 {
630 log<level::INFO>("Transition request initiated successfully");
631 }
vishwa36993272015-11-20 12:43:49 -0600632
633 sd_bus_error_free(&bus_error);
Sergey Solomineb9b8142016-08-23 09:07:28 -0500634 free(busname);
vishwa36993272015-11-20 12:43:49 -0600635
Sergey Solomineb9b8142016-08-23 09:07:28 -0500636 return rc;
vishwa36993272015-11-20 12:43:49 -0600637}
638
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500639struct hostPowerPolicyTypeMap_t
640{
Nan Lifdd8ec52016-08-28 03:57:40 +0800641 uint8_t policyNum;
642 char policyName[19];
643};
644
645hostPowerPolicyTypeMap_t g_hostPowerPolicyTypeMap_t[] = {
646
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500647 {0x00, "LEAVE_OFF"},
648 {0x01, "RESTORE_LAST_STATE"},
649 {0x02, "ALWAYS_POWER_ON"},
650 {0x03, "UNKNOWN"}
Nan Lifdd8ec52016-08-28 03:57:40 +0800651};
652
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500653uint8_t get_host_power_policy(char *p)
654{
Nan Lifdd8ec52016-08-28 03:57:40 +0800655
656 hostPowerPolicyTypeMap_t *s = g_hostPowerPolicyTypeMap_t;
657
658 while (s->policyNum != 0x03) {
659 if (!strcmp(s->policyName,p))
660 break;
661 s++;
662 }
663
664 return s->policyNum;
665}
666
667//----------------------------------------------------------------------
668// Get Chassis Status commands
669//----------------------------------------------------------------------
670ipmi_ret_t ipmi_get_chassis_status(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500671 ipmi_request_t request,
672 ipmi_response_t response,
673 ipmi_data_len_t data_len,
674 ipmi_context_t context)
Nan Lifdd8ec52016-08-28 03:57:40 +0800675{
676 const char *objname = "/org/openbmc/control/power0";
677 const char *intf = "org.openbmc.control.Power";
678
679 sd_bus *bus = NULL;
680 sd_bus_message *reply = NULL;
681 int r = 0;
682 int pgood = 0;
683 char *busname = NULL;
684 ipmi_ret_t rc = IPMI_CC_OK;
685 ipmi_get_chassis_status_t chassis_status{};
686
687 char *p = NULL;
688 uint8_t s = 0;
689
690 // Get the system bus where most system services are provided.
691 bus = ipmid_get_sd_bus_connection();
692
693 *data_len = 4;
694
695 r = mapper_get_service(bus, objname, &busname);
696 if (r < 0) {
697 fprintf(stderr, "Failed to get bus name, return value: %s.\n", strerror(-r));
698 rc = IPMI_CC_UNSPECIFIED_ERROR;
699 goto finish;
700 }
701
702 r = sd_bus_get_property(bus, busname, objname, intf, "pgood", NULL, &reply, "i");
703 if (r < 0) {
704 fprintf(stderr, "Failed to call sd_bus_get_property:%d, %s\n", r, strerror(-r));
705 fprintf(stderr, "Bus: %s, Path: %s, Interface: %s\n",
706 busname, objname, intf);
707 rc = IPMI_CC_UNSPECIFIED_ERROR;
708 goto finish;
709 }
710
711 r = sd_bus_message_read(reply, "i", &pgood);
712 if (r < 0) {
713 fprintf(stderr, "Failed to read sensor: %s\n", strerror(-r));
714 rc = IPMI_CC_UNSPECIFIED_ERROR;
715 goto finish;
716 }
717
718 printf("pgood is 0x%02x\n", pgood);
719
720 // Get Power Policy
721 r = dbus_get_property("power_policy",&p);
722
723 if (r < 0) {
724 fprintf(stderr, "Dbus get property(power_policy) failed for get_sys_boot_options.\n");
725 rc = IPMI_CC_UNSPECIFIED_ERROR;
726 } else {
727 s = get_host_power_policy(p);
728 }
729
730 if (p)
731 {
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500732 free(p);
733 p = NULL;
Nan Lifdd8ec52016-08-28 03:57:40 +0800734 }
735
736 // Current Power State
737 // [7] reserved
738 // [6..5] power restore policy
739 // 00b = chassis stays powered off after AC/mains returns
740 // 01b = after AC returns, power is restored to the state that was
741 // in effect when AC/mains was lost.
742 // 10b = chassis always powers up after AC/mains returns
743 // 11b = unknow
744 // Set to 00b, by observing the hardware behavior.
745 // Do we need to define a dbus property to identify the restore policy?
746
747 // [4] power control fault
748 // 1b = controller attempted to turn system power on or off, but
749 // system did not enter desired state.
750 // Set to 0b, since We don't support it..
751
752 // [3] power fault
753 // 1b = fault detected in main power subsystem.
754 // set to 0b. for we don't support it.
755
756 // [2] 1b = interlock (chassis is presently shut down because a chassis
757 // panel interlock switch is active). (IPMI 1.5)
758 // set to 0b, for we don't support it.
759
760 // [1] power overload
761 // 1b = system shutdown because of power overload condition.
762 // set to 0b, for we don't support it.
763
764 // [0] power is on
765 // 1b = system power is on
766 // 0b = system power is off(soft-off S4/S5, or mechanical off)
767
768 chassis_status.cur_power_state = ((s & 0x3)<<5) | (pgood & 0x1);
769
770 // Last Power Event
771 // [7..5] – reserved
772 // [4] – 1b = last ‘Power is on’ state was entered via IPMI command
773 // [3] – 1b = last power down caused by power fault
774 // [2] – 1b = last power down caused by a power interlock being activated
775 // [1] – 1b = last power down caused by a Power overload
776 // [0] – 1b = AC failed
777 // set to 0x0, for we don't support these fields.
778
779 chassis_status.last_power_event = 0;
780
781 // Misc. Chassis State
782 // [7] – reserved
783 // [6] – 1b = Chassis Identify command and state info supported (Optional)
784 // 0b = Chassis Identify command support unspecified via this command.
785 // (The Get Command Support command , if implemented, would still
786 // indicate support for the Chassis Identify command)
787 // [5..4] – Chassis Identify State. Mandatory when bit[6] =1b, reserved (return
788 // as 00b) otherwise. Returns the present chassis identify state.
789 // Refer to the Chassis Identify command for more info.
790 // 00b = chassis identify state = Off
791 // 01b = chassis identify state = Temporary(timed) On
792 // 10b = chassis identify state = Indefinite On
793 // 11b = reserved
794 // [3] – 1b = Cooling/fan fault detected
795 // [2] – 1b = Drive Fault
796 // [1] – 1b = Front Panel Lockout active (power off and reset via chassis
797 // push-buttons disabled.)
798 // [0] – 1b = Chassis Intrusion active
799 // set to 0, for we don't support them.
800 chassis_status.misc_power_state = 0;
801
802 // Front Panel Button Capabilities and disable/enable status(Optional)
803 // set to 0, for we don't support them.
804 chassis_status.front_panel_button_cap_status = 0;
805
806 // Pack the actual response
807 memcpy(response, &chassis_status, *data_len);
808
809finish:
810 free(busname);
811 reply = sd_bus_message_unref(reply);
812
813 return rc;
814}
Chris Austen7888c4d2015-12-03 15:26:20 -0600815
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +0530816//-------------------------------------------------------------
817// Send a command to SoftPowerOff application to stop any timer
818//-------------------------------------------------------------
819int stop_soft_off_timer()
820{
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +0530821 constexpr auto iface = "org.freedesktop.DBus.Properties";
822 constexpr auto soft_off_iface = "xyz.openbmc_project.Ipmi.Internal."
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500823 "SoftPowerOff";
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +0530824
825 constexpr auto property = "ResponseReceived";
826 constexpr auto value = "xyz.openbmc_project.Ipmi.Internal."
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500827 "SoftPowerOff.HostResponse.HostShutdown";
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +0530828
829 // Get the system bus where most system services are provided.
830 auto bus = ipmid_get_sd_bus_connection();
831
832 // Get the service name
Andrew Geissler2b4e4592017-06-08 11:18:35 -0500833 // TODO openbmc/openbmc#1661 - Mapper refactor
834 //
835 // See openbmc/openbmc#1743 for some details but high level summary is that
836 // for now the code will directly call the soft off interface due to a
837 // race condition with mapper usage
838 //
839 //char *busname = nullptr;
840 //auto r = mapper_get_service(bus, SOFTOFF_OBJPATH, &busname);
841 //if (r < 0)
842 //{
843 // fprintf(stderr, "Failed to get %s bus name: %s\n",
844 // SOFTOFF_OBJPATH, strerror(-r));
845 // return r;
846 //}
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +0530847
848 // No error object or reply expected.
Andrew Geissler2b4e4592017-06-08 11:18:35 -0500849 int rc = sd_bus_call_method(bus, SOFTOFF_BUSNAME, SOFTOFF_OBJPATH, iface,
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500850 "Set", nullptr, nullptr, "ssv",
851 soft_off_iface, property, "s", value);
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +0530852 if (rc < 0)
853 {
854 fprintf(stderr, "Failed to set property in SoftPowerOff object: %s\n",
855 strerror(-rc));
856 }
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500857
Andrew Geissler2b4e4592017-06-08 11:18:35 -0500858 //TODO openbmc/openbmc#1661 - Mapper refactor
859 //free(busname);
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +0530860 return rc;
861}
862
vishwa36993272015-11-20 12:43:49 -0600863//----------------------------------------------------------------------
Andrew Geisslera6e3a302017-05-31 19:34:00 -0500864// Create file to indicate there is no need for softoff notification to host
865//----------------------------------------------------------------------
866void indicate_no_softoff_needed()
867{
868 fs::path path{HOST_INBAND_REQUEST_DIR};
869 if (!fs::is_directory(path))
870 {
871 fs::create_directory(path);
872 }
873
874 // Add the host instance (default 0 for now) to the file name
875 std::string file{HOST_INBAND_REQUEST_FILE};
876 auto size = std::snprintf(nullptr,0,file.c_str(),0);
877 size++; // null
878 std::unique_ptr<char[]> buf(new char[size]);
879 std::snprintf(buf.get(),size,file.c_str(),0);
880
881 // Append file name to directory and create it
882 path /= buf.get();
883 std::ofstream(path.c_str());
884}
885
886//----------------------------------------------------------------------
vishwa36993272015-11-20 12:43:49 -0600887// Chassis Control commands
888//----------------------------------------------------------------------
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500889ipmi_ret_t ipmi_chassis_control(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
890 ipmi_request_t request,
891 ipmi_response_t response,
892 ipmi_data_len_t data_len,
893 ipmi_context_t context)
vishwa36993272015-11-20 12:43:49 -0600894{
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500895 // Error from power off.
896 int rc = 0;
vishwa36993272015-11-20 12:43:49 -0600897
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500898 // No response for this command.
vishwa36993272015-11-20 12:43:49 -0600899 *data_len = 0;
900
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500901 // Catch the actual operaton by peeking into request buffer
902 uint8_t chassis_ctrl_cmd = *(uint8_t *)request;
903 printf("Chassis Control Command: Operation:[0x%X]\n",chassis_ctrl_cmd);
vishwa36993272015-11-20 12:43:49 -0600904
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500905 switch(chassis_ctrl_cmd)
906 {
907 case CMD_POWER_ON:
908 rc = initiate_state_transition(State::Host::Transition::On);
909 break;
910 case CMD_POWER_OFF:
911 // Need to Nudge SoftPowerOff application that it needs to stop the
912 // watchdog timer if running.
913 rc = stop_soft_off_timer();
Andrew Geisslera6e3a302017-05-31 19:34:00 -0500914 // Only request the Off transition if the soft power off
915 // application is not running
916 if (rc < 0)
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500917 {
Andrew Geisslera6e3a302017-05-31 19:34:00 -0500918 log<level::INFO>("Did not find soft off service so request "
919 "Host:Transition:Off");
920
921 // First create a file to indicate to the soft off application
922 // that it should not run since this is a direct user initiated
923 // power off request (i.e. a power off request that is not
924 // originating via a soft power off SMS request)
925 indicate_no_softoff_needed();
926
927 // Now request the shutdown
928 rc = initiate_state_transition(State::Host::Transition::Off);
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500929 }
Andrew Geisslera6e3a302017-05-31 19:34:00 -0500930 else
931 {
932 log<level::INFO>("Soft off is running, so let that stop "
933 "the host");
934 }
935
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500936 break;
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +0530937
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500938 case CMD_HARD_RESET:
939 case CMD_POWER_CYCLE:
940 // SPEC has a section that says certain implementations can trigger
941 // PowerOn if power is Off when a command to power cycle is
942 // requested
Andrew Geisslera6e3a302017-05-31 19:34:00 -0500943
944 // First create a file to indicate to the soft off application
945 // that it should not run since this is a direct user initiated
946 // power reboot request (i.e. a reboot request that is not
947 // originating via a soft power off SMS request)
948 indicate_no_softoff_needed();
949
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500950 rc = initiate_state_transition(State::Host::Transition::Reboot);
951 break;
952 default:
953 {
954 fprintf(stderr, "Invalid Chassis Control command:[0x%X] received\n",chassis_ctrl_cmd);
955 rc = -1;
956 }
957 }
vishwa36993272015-11-20 12:43:49 -0600958
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500959 return ( (rc < 0) ? IPMI_CC_INVALID : IPMI_CC_OK);
vishwa36993272015-11-20 12:43:49 -0600960}
961
shgoupfd84fbbf2015-12-17 10:05:51 +0800962struct bootOptionTypeMap_t {
963 uint8_t ipmibootflag;
964 char dbusname[8];
965};
966
967#define INVALID_STRING "Invalid"
968// dbus supports this list of boot devices.
969bootOptionTypeMap_t g_bootOptionTypeMap_t[] = {
970
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500971 {0x01, "Network"},
972 {0x02, "Disk"},
973 {0x03, "Safe"},
974 {0x05, "CDROM"},
975 {0x06, "Setup"},
976 {0x00, "Default"},
977 {0xFF, INVALID_STRING}
shgoupfd84fbbf2015-12-17 10:05:51 +0800978};
979
980uint8_t get_ipmi_boot_option(char *p) {
981
982 bootOptionTypeMap_t *s = g_bootOptionTypeMap_t;
983
984 while (s->ipmibootflag != 0xFF) {
985 if (!strcmp(s->dbusname,p))
986 break;
987 s++;
988 }
989
990 if (!s->ipmibootflag)
991 printf("Failed to find Sensor Type %s\n", p);
992
993 return s->ipmibootflag;
994}
995
996char* get_boot_option_by_ipmi(uint8_t p) {
997
998 bootOptionTypeMap_t *s = g_bootOptionTypeMap_t;
999
1000 while (s->ipmibootflag != 0xFF) {
1001
1002 if (s->ipmibootflag == p)
1003 break;
1004
1005 s++;
1006 }
1007
1008
1009 if (!s->ipmibootflag)
1010 printf("Failed to find Sensor Type 0x%x\n", p);
1011
1012 return s->dbusname;
1013}
1014
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001015ipmi_ret_t ipmi_chassis_get_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1016 ipmi_request_t request,
1017 ipmi_response_t response,
1018 ipmi_data_len_t data_len,
1019 ipmi_context_t context)
Adriana Kobylak40814c62015-10-27 15:58:44 -05001020{
shgoupfd84fbbf2015-12-17 10:05:51 +08001021 ipmi_ret_t rc = IPMI_CC_PARM_NOT_SUPPORTED;
1022 char *p = NULL;
1023 get_sys_boot_options_response_t *resp = (get_sys_boot_options_response_t *) response;
1024 get_sys_boot_options_t *reqptr = (get_sys_boot_options_t*) request;
1025 uint8_t s;
Adriana Kobylak40814c62015-10-27 15:58:44 -05001026
1027 printf("IPMI GET_SYS_BOOT_OPTIONS\n");
1028
shgoupfd84fbbf2015-12-17 10:05:51 +08001029 memset(resp,0,sizeof(*resp));
1030 resp->version = SET_PARM_VERSION;
1031 resp->parm = 5;
ratagupta6f6bff2016-04-04 06:20:11 -05001032 resp->data[0] = SET_PARM_BOOT_FLAGS_VALID_ONE_TIME;
Adriana Kobylak40814c62015-10-27 15:58:44 -05001033
Adriana Kobylak40814c62015-10-27 15:58:44 -05001034
shgoupfd84fbbf2015-12-17 10:05:51 +08001035 /*
1036 * Parameter #5 means boot flags. Please refer to 28.13 of ipmi doc.
1037 * This is the only parameter used by petitboot.
1038 */
Ratan Guptafd28dd72016-08-01 04:58:01 -05001039 if ( reqptr->parameter == static_cast<uint8_t>
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001040 ( BootOptionParameter::BOOT_FLAGS )) {
shgoupfd84fbbf2015-12-17 10:05:51 +08001041
Ratan Guptafd28dd72016-08-01 04:58:01 -05001042 *data_len = static_cast<uint8_t>(BootOptionResponseSize::BOOT_FLAGS);
ratagupta6f6bff2016-04-04 06:20:11 -05001043 /* Get the boot device */
1044 int r = dbus_get_property("boot_flags",&p);
shgoupfd84fbbf2015-12-17 10:05:51 +08001045
1046 if (r < 0) {
ratagupta6f6bff2016-04-04 06:20:11 -05001047 fprintf(stderr, "Dbus get property(boot_flags) failed for get_sys_boot_options.\n");
shgoupfd84fbbf2015-12-17 10:05:51 +08001048 rc = IPMI_CC_UNSPECIFIED_ERROR;
1049
1050 } else {
1051
1052 s = get_ipmi_boot_option(p);
1053 resp->data[1] = (s << 2);
1054 rc = IPMI_CC_OK;
ratagupta6f6bff2016-04-04 06:20:11 -05001055
shgoupfd84fbbf2015-12-17 10:05:51 +08001056 }
1057
ratagupta6f6bff2016-04-04 06:20:11 -05001058 if (p)
1059 {
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001060 free(p);
1061 p = NULL;
ratagupta6f6bff2016-04-04 06:20:11 -05001062 }
1063
1064 /* Get the boot policy */
1065 r = dbus_get_property("boot_policy",&p);
1066
1067 if (r < 0) {
1068 fprintf(stderr, "Dbus get property(boot_policy) failed for get_sys_boot_options.\n");
1069 rc = IPMI_CC_UNSPECIFIED_ERROR;
1070
1071 } else {
1072
Ratan Guptafd28dd72016-08-01 04:58:01 -05001073 printf("BootPolicy is[%s]", p);
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001074 resp->data[0] = (strncmp(p,"ONETIME",strlen("ONETIME"))==0) ?
1075 SET_PARM_BOOT_FLAGS_VALID_ONE_TIME:
1076 SET_PARM_BOOT_FLAGS_VALID_PERMANENT;
ratagupta6f6bff2016-04-04 06:20:11 -05001077 rc = IPMI_CC_OK;
1078
1079 }
1080
1081
Ratan Guptafd28dd72016-08-01 04:58:01 -05001082 } else if ( reqptr->parameter == static_cast<uint8_t>
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001083 ( BootOptionParameter::OPAL_NETWORK_SETTINGS )) {
Ratan Guptafd28dd72016-08-01 04:58:01 -05001084
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001085 *data_len = static_cast<uint8_t>(BootOptionResponseSize::OPAL_NETWORK_SETTINGS);
Ratan Guptafd28dd72016-08-01 04:58:01 -05001086
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001087 resp->parm = static_cast<uint8_t>(BootOptionParameter::OPAL_NETWORK_SETTINGS);
Ratan Guptafd28dd72016-08-01 04:58:01 -05001088
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001089 int ret = getHostNetworkData(resp);
Ratan Guptafd28dd72016-08-01 04:58:01 -05001090
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001091 if (ret < 0) {
Ratan Guptafd28dd72016-08-01 04:58:01 -05001092
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001093 fprintf(stderr, "getHostNetworkData failed for get_sys_boot_options.\n");
1094 rc = IPMI_CC_UNSPECIFIED_ERROR;
Ratan Guptafd28dd72016-08-01 04:58:01 -05001095
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001096 }else
1097 rc = IPMI_CC_OK;
Ratan Guptafd28dd72016-08-01 04:58:01 -05001098 }
1099
1100 else {
Adriana Kobylak40814c62015-10-27 15:58:44 -05001101 fprintf(stderr, "Unsupported parameter 0x%x\n", reqptr->parameter);
shgoupfd84fbbf2015-12-17 10:05:51 +08001102 }
1103
1104 if (p)
1105 free(p);
1106
Ratan Guptafd28dd72016-08-01 04:58:01 -05001107 if (rc == IPMI_CC_OK)
1108 {
1109 *data_len += 2;
1110 }
1111
shgoupfd84fbbf2015-12-17 10:05:51 +08001112 return rc;
1113}
1114
1115
1116
1117ipmi_ret_t ipmi_chassis_set_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001118 ipmi_request_t request,
1119 ipmi_response_t response,
1120 ipmi_data_len_t data_len,
1121 ipmi_context_t context)
shgoupfd84fbbf2015-12-17 10:05:51 +08001122{
1123 ipmi_ret_t rc = IPMI_CC_OK;
1124 char *s;
shgoupfd84fbbf2015-12-17 10:05:51 +08001125 set_sys_boot_options_t *reqptr = (set_sys_boot_options_t *) request;
1126
Ratan Guptafd28dd72016-08-01 04:58:01 -05001127 printf("IPMI SET_SYS_BOOT_OPTIONS reqptr->parameter =[%d]\n",reqptr->parameter);
1128
shgoupfd84fbbf2015-12-17 10:05:51 +08001129 // This IPMI command does not have any resposne data
1130 *data_len = 0;
1131
1132 /* 000101
1133 * Parameter #5 means boot flags. Please refer to 28.13 of ipmi doc.
1134 * This is the only parameter used by petitboot.
1135 */
Ratan Guptafd28dd72016-08-01 04:58:01 -05001136
1137 if (reqptr->parameter == (uint8_t)BootOptionParameter::BOOT_FLAGS) {
shgoupfd84fbbf2015-12-17 10:05:51 +08001138
1139 s = get_boot_option_by_ipmi(((reqptr->data[1] & 0x3C) >> 2));
1140
1141 printf("%d: %s\n", __LINE__, s);
1142 if (!strcmp(s,INVALID_STRING)) {
1143
1144 rc = IPMI_CC_PARM_NOT_SUPPORTED;
1145
1146 } else {
1147
ratagupta6f6bff2016-04-04 06:20:11 -05001148 int r = dbus_set_property("boot_flags",s);
shgoupfd84fbbf2015-12-17 10:05:51 +08001149
1150 if (r < 0) {
ratagupta6f6bff2016-04-04 06:20:11 -05001151 fprintf(stderr, "Dbus set property(boot_flags) failed for set_sys_boot_options.\n");
shgoupfd84fbbf2015-12-17 10:05:51 +08001152 rc = IPMI_CC_UNSPECIFIED_ERROR;
1153 }
1154 }
Ratan Guptafd28dd72016-08-01 04:58:01 -05001155
ratagupta6f6bff2016-04-04 06:20:11 -05001156 /* setting the boot policy */
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001157 s = (char *)(((reqptr->data[0] & SET_PARM_BOOT_FLAGS_PERMANENT) ==
1158 SET_PARM_BOOT_FLAGS_PERMANENT) ?"PERMANENT":"ONETIME");
ratagupta6f6bff2016-04-04 06:20:11 -05001159
Ratan Guptafd28dd72016-08-01 04:58:01 -05001160 printf ( "\nBoot Policy is %s",s);
ratagupta6f6bff2016-04-04 06:20:11 -05001161 int r = dbus_set_property("boot_policy",s);
1162
1163 if (r < 0) {
1164 fprintf(stderr, "Dbus set property(boot_policy) failed for set_sys_boot_options.\n");
1165 rc = IPMI_CC_UNSPECIFIED_ERROR;
1166 }
shgoupfd84fbbf2015-12-17 10:05:51 +08001167
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001168 } else if (reqptr->parameter ==
1169 (uint8_t)BootOptionParameter::OPAL_NETWORK_SETTINGS) {
Ratan Guptafd28dd72016-08-01 04:58:01 -05001170
1171 int ret = setHostNetworkData(reqptr);
1172 if (ret < 0) {
1173 fprintf(stderr, "setHostNetworkData failed for set_sys_boot_options.\n");
1174 rc = IPMI_CC_UNSPECIFIED_ERROR;
1175 }
1176 }
1177 else {
shgoupfd84fbbf2015-12-17 10:05:51 +08001178 fprintf(stderr, "Unsupported parameter 0x%x\n", reqptr->parameter);
1179 rc = IPMI_CC_PARM_NOT_SUPPORTED;
Adriana Kobylak40814c62015-10-27 15:58:44 -05001180 }
1181
1182 return rc;
1183}
1184
1185void register_netfn_chassis_functions()
1186{
Tom05732372016-09-06 17:21:23 +05301187 // <Wildcard Command>
Adriana Kobylak40814c62015-10-27 15:58:44 -05001188 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_CHASSIS, IPMI_CMD_WILDCARD);
Tom05732372016-09-06 17:21:23 +05301189 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_WILDCARD, NULL, ipmi_chassis_wildcard,
1190 PRIVILEGE_USER);
Adriana Kobylak40814c62015-10-27 15:58:44 -05001191
Tom05732372016-09-06 17:21:23 +05301192 // Get Chassis Capabilities
Nan Li8d15fb42016-08-16 22:29:40 +08001193 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_CHASSIS, IPMI_CMD_GET_CHASSIS_CAP);
Tom05732372016-09-06 17:21:23 +05301194 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_GET_CHASSIS_CAP, NULL, ipmi_get_chassis_cap,
1195 PRIVILEGE_USER);
Nan Li8d15fb42016-08-16 22:29:40 +08001196
Tom05732372016-09-06 17:21:23 +05301197 // <Get System Boot Options>
Adriana Kobylak40814c62015-10-27 15:58:44 -05001198 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_CHASSIS, IPMI_CMD_GET_SYS_BOOT_OPTIONS);
Tom05732372016-09-06 17:21:23 +05301199 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_GET_SYS_BOOT_OPTIONS, NULL,
1200 ipmi_chassis_get_sys_boot_options, PRIVILEGE_OPERATOR);
Adriana Kobylak40814c62015-10-27 15:58:44 -05001201
Tom05732372016-09-06 17:21:23 +05301202 // <Get Chassis Status>
Nan Lifdd8ec52016-08-28 03:57:40 +08001203 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_CHASSIS, IPMI_CMD_CHASSIS_STATUS);
Tom05732372016-09-06 17:21:23 +05301204 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_CHASSIS_STATUS, NULL, ipmi_get_chassis_status,
1205 PRIVILEGE_USER);
Nan Lifdd8ec52016-08-28 03:57:40 +08001206
Tom05732372016-09-06 17:21:23 +05301207 // <Chassis Control>
vishwa36993272015-11-20 12:43:49 -06001208 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_CHASSIS, IPMI_CMD_CHASSIS_CONTROL);
Tom05732372016-09-06 17:21:23 +05301209 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_CHASSIS_CONTROL, NULL, ipmi_chassis_control,
1210 PRIVILEGE_OPERATOR);
shgoupfd84fbbf2015-12-17 10:05:51 +08001211
Tom05732372016-09-06 17:21:23 +05301212 // <Set System Boot Options>
shgoupfd84fbbf2015-12-17 10:05:51 +08001213 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n", NETFUN_CHASSIS, IPMI_CMD_SET_SYS_BOOT_OPTIONS);
Tom05732372016-09-06 17:21:23 +05301214 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_SET_SYS_BOOT_OPTIONS, NULL,
1215 ipmi_chassis_set_sys_boot_options, PRIVILEGE_OPERATOR);
vishwa36993272015-11-20 12:43:49 -06001216}