blob: 9009cd62adb4e99ccd212deb7f182bc8bd81b9a6 [file] [log] [blame]
vishwabmcba0bd5f2015-09-30 16:50:23 +05301#include <stdio.h>
2#include <dlfcn.h>
3#include <iostream>
4#include <unistd.h>
5#include <assert.h>
6#include <dirent.h>
Chris Austen0ba649e2015-10-13 12:28:13 -05007#include <systemd/sd-bus.h>
vishwabmcba0bd5f2015-09-30 16:50:23 +05308#include <string.h>
9#include <stdlib.h>
10#include <map>
11#include "ipmid.H"
Chris Austen0ba649e2015-10-13 12:28:13 -050012#include <sys/time.h>
13#include <errno.h>
Chris Austen0012e9b2015-10-22 01:37:46 -050014#include "sensorhandler.h"
Chris Austen0ba649e2015-10-13 12:28:13 -050015
Chris Austen0ba649e2015-10-13 12:28:13 -050016sd_bus *bus = NULL;
vishwab9f559a2016-01-13 01:53:08 -060017sd_bus_slot *ipmid_slot = NULL;
Chris Austen30195fa2015-11-13 14:39:19 -060018
Chris Austen41a4b312015-10-25 03:45:42 -050019FILE *ipmiio, *ipmidbus, *ipmicmddetails;
vishwabmcba0bd5f2015-09-30 16:50:23 +053020
Chris Austen99497312015-10-22 13:00:16 -050021void print_usage(void) {
22 fprintf(stderr, "Options: [-d mask]\n");
23 fprintf(stderr, " mask : 0x01 - Print ipmi packets\n");
24 fprintf(stderr, " mask : 0x02 - Print DBUS operations\n");
25 fprintf(stderr, " mask : 0x04 - Print ipmi command details\n");
26 fprintf(stderr, " mask : 0xFF - Print all trace\n");
27}
28
29
30
Jeremy Kerre41081f2015-10-27 12:11:36 +080031const char * DBUS_INTF = "org.openbmc.HostIpmi";
vishwabmcba0bd5f2015-09-30 16:50:23 +053032
Jeremy Kerre41081f2015-10-27 12:11:36 +080033const char * FILTER = "type='signal',interface='org.openbmc.HostIpmi',member='ReceivedMessage'";
Chris Austen0ba649e2015-10-13 12:28:13 -050034
35
vishwabmcba0bd5f2015-09-30 16:50:23 +053036typedef std::pair<ipmi_netfn_t, ipmi_cmd_t> ipmi_fn_cmd_t;
37typedef std::pair<ipmid_callback_t, ipmi_context_t> ipmi_fn_context_t;
38
39// Global data structure that contains the IPMI command handler's registrations.
40std::map<ipmi_fn_cmd_t, ipmi_fn_context_t> g_ipmid_router_map;
41
Chris Austen0ba649e2015-10-13 12:28:13 -050042
Chris Austen0ba649e2015-10-13 12:28:13 -050043#ifndef HEXDUMP_COLS
44#define HEXDUMP_COLS 16
45#endif
46
Chris Austen99497312015-10-22 13:00:16 -050047void hexdump(FILE *s, void *mem, size_t len)
Chris Austen0ba649e2015-10-13 12:28:13 -050048{
49 unsigned int i, j;
Chris Austen120f7322015-10-14 23:27:31 -050050
Chris Austen0ba649e2015-10-13 12:28:13 -050051 for(i = 0; i < len + ((len % HEXDUMP_COLS) ? (HEXDUMP_COLS - len % HEXDUMP_COLS) : 0); i++)
52 {
53 /* print offset */
54 if(i % HEXDUMP_COLS == 0)
55 {
Chris Austen99497312015-10-22 13:00:16 -050056 fprintf(s,"0x%06x: ", i);
Chris Austen0ba649e2015-10-13 12:28:13 -050057 }
Chris Austen120f7322015-10-14 23:27:31 -050058
Chris Austen0ba649e2015-10-13 12:28:13 -050059 /* print hex data */
60 if(i < len)
61 {
Chris Austen99497312015-10-22 13:00:16 -050062 fprintf(s,"%02x ", 0xFF & ((char*)mem)[i]);
Chris Austen0ba649e2015-10-13 12:28:13 -050063 }
64 else /* end of block, just aligning for ASCII dump */
65 {
Chris Austen99497312015-10-22 13:00:16 -050066 fprintf(s," ");
Chris Austen0ba649e2015-10-13 12:28:13 -050067 }
Chris Austen120f7322015-10-14 23:27:31 -050068
Chris Austen0ba649e2015-10-13 12:28:13 -050069 /* print ASCII dump */
70 if(i % HEXDUMP_COLS == (HEXDUMP_COLS - 1))
71 {
72 for(j = i - (HEXDUMP_COLS - 1); j <= i; j++)
73 {
74 if(j >= len) /* end of block, not really printing */
75 {
Chris Austen99497312015-10-22 13:00:16 -050076 fputc(' ', s);
Chris Austen0ba649e2015-10-13 12:28:13 -050077 }
78 else if(isprint(((char*)mem)[j])) /* printable char */
79 {
Chris Austen99497312015-10-22 13:00:16 -050080 fputc(0xFF & ((char*)mem)[j], s);
Chris Austen0ba649e2015-10-13 12:28:13 -050081 }
82 else /* other char */
83 {
Chris Austen99497312015-10-22 13:00:16 -050084 fputc('.',s);
Chris Austen0ba649e2015-10-13 12:28:13 -050085 }
86 }
Chris Austen99497312015-10-22 13:00:16 -050087 fputc('\n',s);
Chris Austen0ba649e2015-10-13 12:28:13 -050088 }
89 }
90}
91
92
vishwabmcba0bd5f2015-09-30 16:50:23 +053093// Method that gets called by shared libraries to get their command handlers registered
94void ipmi_register_callback(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
95 ipmi_context_t context, ipmid_callback_t handler)
96{
97 // Pack NetFn and Command in one.
98 auto netfn_and_cmd = std::make_pair(netfn, cmd);
99
100 // Pack Function handler and Data in another.
101 auto handler_and_context = std::make_pair(handler, context);
102
103 // Check if the registration has already been made..
104 auto iter = g_ipmid_router_map.find(netfn_and_cmd);
105 if(iter != g_ipmid_router_map.end())
106 {
107 fprintf(stderr,"ERROR : Duplicate registration for NetFn [0x%X], Cmd:[0x%X]\n",netfn, cmd);
108 }
109 else
110 {
111 // This is a fresh registration.. Add it to the map.
112 g_ipmid_router_map.emplace(netfn_and_cmd, handler_and_context);
113 }
114
115 return;
116}
117
118// Looks at the map and calls corresponding handler functions.
119ipmi_ret_t ipmi_netfn_router(ipmi_netfn_t netfn, ipmi_cmd_t cmd, ipmi_request_t request,
120 ipmi_response_t response, ipmi_data_len_t data_len)
121{
122 // return from the Command handlers.
123 ipmi_ret_t rc = IPMI_CC_INVALID;
124
125 // Walk the map that has the registered handlers and invoke the approprite
126 // handlers for matching commands.
127 auto iter = g_ipmid_router_map.find(std::make_pair(netfn, cmd));
128 if(iter == g_ipmid_router_map.end())
129 {
Chris Austen99497312015-10-22 13:00:16 -0500130 fprintf(stderr, "No registered handlers for NetFn:[0x%X], Cmd:[0x%X]"
vishwabmcba0bd5f2015-09-30 16:50:23 +0530131 " trying Wilcard implementation \n",netfn, cmd);
132
133 // Now that we did not find any specific [NetFn,Cmd], tuple, check for
134 // NetFn, WildCard command present.
135 iter = g_ipmid_router_map.find(std::make_pair(netfn, IPMI_CMD_WILDCARD));
136 if(iter == g_ipmid_router_map.end())
137 {
Chris Austen99497312015-10-22 13:00:16 -0500138 fprintf(stderr, "No Registered handlers for NetFn:[0x%X],Cmd:[0x%X]\n",netfn, IPMI_CMD_WILDCARD);
vishwabmcba0bd5f2015-09-30 16:50:23 +0530139
140 // Respond with a 0xC1
141 memcpy(response, &rc, IPMI_CC_LEN);
142 *data_len = IPMI_CC_LEN;
143 return rc;
144 }
145 }
146
147#ifdef __IPMI_DEBUG__
148 // We have either a perfect match -OR- a wild card atleast,
149 printf("Calling Net function:[0x%X], Command:[0x%X]\n", netfn, cmd);
150#endif
151
152 // Extract the map data onto appropriate containers
153 auto handler_and_context = iter->second;
154
155 // Creating a pointer type casted to char* to make sure we advance 1 byte
156 // when we advance pointer to next's address. advancing void * would not
157 // make sense.
158 char *respo = &((char *)response)[IPMI_CC_LEN];
159
160 // Response message from the plugin goes into a byte post the base response
161 rc = (handler_and_context.first) (netfn, cmd, request, respo,
162 data_len, handler_and_context.second);
Chris Austen120f7322015-10-14 23:27:31 -0500163
vishwabmcba0bd5f2015-09-30 16:50:23 +0530164 // Now copy the return code that we got from handler and pack it in first
165 // byte.
166 memcpy(response, &rc, IPMI_CC_LEN);
Chris Austen120f7322015-10-14 23:27:31 -0500167
vishwabmcba0bd5f2015-09-30 16:50:23 +0530168 // Data length is now actual data + completion code.
169 *data_len = *data_len + IPMI_CC_LEN;
170
171 return rc;
172}
173
vishwabmcba0bd5f2015-09-30 16:50:23 +0530174
vishwabmcba0bd5f2015-09-30 16:50:23 +0530175
vishwabmcba0bd5f2015-09-30 16:50:23 +0530176
Jeremy Kerr2564b1a2015-10-27 13:37:17 +0800177static int send_ipmi_message(sd_bus_message *req, unsigned char seq, unsigned char netfn, unsigned char lun, unsigned char cmd, unsigned char cc, unsigned char *buf, unsigned char len) {
vishwabmcba0bd5f2015-09-30 16:50:23 +0530178
Chris Austen0ba649e2015-10-13 12:28:13 -0500179 sd_bus_error error = SD_BUS_ERROR_NULL;
180 sd_bus_message *reply = NULL, *m=NULL;
Jeremy Kerre41081f2015-10-27 12:11:36 +0800181 const char *dest, *path;
Chris Austen0ba649e2015-10-13 12:28:13 -0500182 int r, pty;
vishwabmcba0bd5f2015-09-30 16:50:23 +0530183
Jeremy Kerre41081f2015-10-27 12:11:36 +0800184 dest = sd_bus_message_get_sender(req);
185 path = sd_bus_message_get_path(req);
vishwabmcba0bd5f2015-09-30 16:50:23 +0530186
Jeremy Kerre41081f2015-10-27 12:11:36 +0800187 r = sd_bus_message_new_method_call(bus,&m,dest,path,DBUS_INTF,"sendMessage");
Chris Austen0ba649e2015-10-13 12:28:13 -0500188 if (r < 0) {
189 fprintf(stderr, "Failed to add the method object: %s\n", strerror(-r));
190 return -1;
vishwabmcba0bd5f2015-09-30 16:50:23 +0530191 }
192
vishwabmcba0bd5f2015-09-30 16:50:23 +0530193
Chris Austenabfb5e82015-10-13 12:29:24 -0500194 // Responses in IPMI require a bit set. So there ya go...
Jeremy Kerr2564b1a2015-10-27 13:37:17 +0800195 netfn |= 0x01;
vishwabmcba0bd5f2015-09-30 16:50:23 +0530196
Chris Austen0ba649e2015-10-13 12:28:13 -0500197
198 // Add the bytes needed for the methods to be called
Jeremy Kerr2564b1a2015-10-27 13:37:17 +0800199 r = sd_bus_message_append(m, "yyyyy", seq, netfn, lun, cmd, cc);
Chris Austen0ba649e2015-10-13 12:28:13 -0500200 if (r < 0) {
201 fprintf(stderr, "Failed add the netfn and others : %s\n", strerror(-r));
Chris Austen169395e2015-12-02 20:56:15 -0600202 goto final;
Chris Austen0ba649e2015-10-13 12:28:13 -0500203 }
Chris Austen120f7322015-10-14 23:27:31 -0500204
Chris Austen0ba649e2015-10-13 12:28:13 -0500205 r = sd_bus_message_append_array(m, 'y', buf, len);
206 if (r < 0) {
207 fprintf(stderr, "Failed to add the string of response bytes: %s\n", strerror(-r));
Chris Austen169395e2015-12-02 20:56:15 -0600208 goto final;
Chris Austen0ba649e2015-10-13 12:28:13 -0500209 }
210
211
212
213 // Call the IPMI responder on the bus so the message can be sent to the CEC
214 r = sd_bus_call(bus, m, 0, &error, &reply);
215 if (r < 0) {
Chris Austen169395e2015-12-02 20:56:15 -0600216 fprintf(stderr, "Failed to call the method: %s\n", strerror(-r));
Chris Austen6bd23962015-12-07 21:31:48 -0600217 fprintf(stderr, "Dest: %s, Path: %s\n", dest, path);
Chris Austen169395e2015-12-02 20:56:15 -0600218 goto final;
Chris Austen0ba649e2015-10-13 12:28:13 -0500219 }
220
221 r = sd_bus_message_read(reply, "x", &pty);
Chris Austen0ba649e2015-10-13 12:28:13 -0500222 if (r < 0) {
223 fprintf(stderr, "Failed to get a rc from the method: %s\n", strerror(-r));
Chris Austen0ba649e2015-10-13 12:28:13 -0500224 }
225
Chris Austen169395e2015-12-02 20:56:15 -0600226final:
Chris Austen0ba649e2015-10-13 12:28:13 -0500227 sd_bus_error_free(&error);
vishwa1eaea4f2016-02-26 11:57:40 -0600228 m = sd_bus_message_unref(m);
229 reply = sd_bus_message_unref(reply);
Chris Austen0ba649e2015-10-13 12:28:13 -0500230
Chris Austen0ba649e2015-10-13 12:28:13 -0500231 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
Chris Austen0ba649e2015-10-13 12:28:13 -0500232}
233
234static int handle_ipmi_command(sd_bus_message *m, void *user_data, sd_bus_error
235 *ret_error) {
236 int r = 0;
Jeremy Kerr2564b1a2015-10-27 13:37:17 +0800237 unsigned char sequence, netfn, lun, cmd;
Chris Austen0ba649e2015-10-13 12:28:13 -0500238 const void *request;
239 size_t sz;
240 size_t resplen =MAX_IPMI_BUFFER;
241 unsigned char response[MAX_IPMI_BUFFER];
242
Chris Austen0ba649e2015-10-13 12:28:13 -0500243 memset(response, 0, MAX_IPMI_BUFFER);
244
Jeremy Kerr2564b1a2015-10-27 13:37:17 +0800245 r = sd_bus_message_read(m, "yyyy", &sequence, &netfn, &lun, &cmd);
Chris Austen0ba649e2015-10-13 12:28:13 -0500246 if (r < 0) {
247 fprintf(stderr, "Failed to parse signal message: %s\n", strerror(-r));
248 return -1;
249 }
250
251 r = sd_bus_message_read_array(m, 'y', &request, &sz );
252 if (r < 0) {
253 fprintf(stderr, "Failed to parse signal message: %s\n", strerror(-r));
254 return -1;
255 }
256
Chris Austen99497312015-10-22 13:00:16 -0500257 fprintf(ipmiio, "IPMI Incoming: Seq 0x%02x, NetFn 0x%02x, CMD: 0x%02x \n", sequence, netfn, cmd);
258 hexdump(ipmiio, (void*)request, sz);
Chris Austen0ba649e2015-10-13 12:28:13 -0500259
Chris Austen120f7322015-10-14 23:27:31 -0500260 // Allow the length field to be used for both input and output of the
Chris Austen0ba649e2015-10-13 12:28:13 -0500261 // ipmi call
262 resplen = sz;
263
Chris Austen120f7322015-10-14 23:27:31 -0500264 // Now that we have parsed the entire byte array from the caller
vishwabmcba0bd5f2015-09-30 16:50:23 +0530265 // we can call the ipmi router to do the work...
Chris Austen0ba649e2015-10-13 12:28:13 -0500266 r = ipmi_netfn_router(netfn, cmd, (void *)request, (void *)response, &resplen);
267 if(r != 0)
vishwabmcba0bd5f2015-09-30 16:50:23 +0530268 {
Chris Austen0ba649e2015-10-13 12:28:13 -0500269 fprintf(stderr,"ERROR:[0x%X] handling NetFn:[0x%X], Cmd:[0x%X]\n",r, netfn, cmd);
Nan Li80be4b92016-05-23 19:30:49 +0800270
271 if(r == -1) {
272 response[0] = IPMI_CC_UNSPECIFIED_ERROR;
273 }
vishwabmcba0bd5f2015-09-30 16:50:23 +0530274 }
275
Chris Austen99497312015-10-22 13:00:16 -0500276 fprintf(ipmiio, "IPMI Response:\n");
277 hexdump(ipmiio, (void*)response, resplen);
vishwabmcba0bd5f2015-09-30 16:50:23 +0530278
Chris Austen0ba649e2015-10-13 12:28:13 -0500279 // Send the response buffer from the ipmi command
Jeremy Kerr2564b1a2015-10-27 13:37:17 +0800280 r = send_ipmi_message(m, sequence, netfn, lun, cmd, response[0],
281 ((unsigned char *)response) + 1, resplen - 1);
Chris Austen0ba649e2015-10-13 12:28:13 -0500282 if (r < 0) {
283 fprintf(stderr, "Failed to send the response message\n");
284 return -1;
vishwabmcba0bd5f2015-09-30 16:50:23 +0530285 }
286
vishwabmcba0bd5f2015-09-30 16:50:23 +0530287
Chris Austen0ba649e2015-10-13 12:28:13 -0500288 return 0;
vishwabmcba0bd5f2015-09-30 16:50:23 +0530289}
290
Chris Austen0ba649e2015-10-13 12:28:13 -0500291
vishwabmcba0bd5f2015-09-30 16:50:23 +0530292//----------------------------------------------------------------------
293// handler_select
294// Select all the files ending with with .so. in the given diretcory
295// @d: dirent structure containing the file name
296//----------------------------------------------------------------------
297int handler_select(const struct dirent *entry)
298{
299 // To hold ".so" from entry->d_name;
300 char dname_copy[4] = {0};
301
302 // We want to avoid checking for everything and isolate to the ones having
303 // .so in them.
304 if(strstr(entry->d_name, IPMI_PLUGIN_EXTN))
305 {
306 // It is possible that .so could be anywhere in the string but unlikely
Chris Austen120f7322015-10-14 23:27:31 -0500307 // But being careful here. Get the base address of the string, move
vishwabmcba0bd5f2015-09-30 16:50:23 +0530308 // until end and come back 3 steps and that gets what we need.
309 strcpy(dname_copy, (entry->d_name + strlen(entry->d_name)-strlen(IPMI_PLUGIN_EXTN)));
310 if(strcmp(dname_copy, IPMI_PLUGIN_EXTN) == 0)
311 {
312 return 1;
313 }
314 }
315 return 0;
316}
317
318// This will do a dlopen of every .so in ipmi_lib_path and will dlopen everything so that they will
Chris Austen120f7322015-10-14 23:27:31 -0500319// register a callback handler
vishwabmcba0bd5f2015-09-30 16:50:23 +0530320void ipmi_register_callback_handlers(const char* ipmi_lib_path)
321{
322 // For walking the ipmi_lib_path
323 struct dirent **handler_list;
324 int num_handlers = 0;
325
326 // This is used to check and abort if someone tries to register a bad one.
327 void *lib_handler = NULL;
328
329 if(ipmi_lib_path == NULL)
330 {
331 fprintf(stderr,"ERROR; No handlers to be registered for ipmi.. Aborting\n");
332 assert(0);
333 }
334 else
335 {
336 // 1: Open ipmi_lib_path. Its usually "/usr/lib/phosphor-host-ipmid"
337 // 2: Scan the directory for the files that end with .so
Chris Austen120f7322015-10-14 23:27:31 -0500338 // 3: For each one of them, just do a 'dlopen' so that they register
vishwabmcba0bd5f2015-09-30 16:50:23 +0530339 // the handlers for callback routines.
340
341 std::string handler_fqdn = ipmi_lib_path;
Chris Austen120f7322015-10-14 23:27:31 -0500342
vishwabmcba0bd5f2015-09-30 16:50:23 +0530343 // Append a "/" since we need to add the name of the .so. If there is
344 // already a .so, adding one more is not any harm.
345 handler_fqdn += "/";
346
347 num_handlers = scandir(ipmi_lib_path, &handler_list, handler_select, alphasort);
Jeremy Kerr5e8f85e2015-10-27 13:43:54 +0800348 if (num_handlers < 0)
349 return;
350
vishwabmcba0bd5f2015-09-30 16:50:23 +0530351 while(num_handlers--)
352 {
Chris Austen54030262015-10-13 12:30:46 -0500353 handler_fqdn = ipmi_lib_path;
vishwabmcba0bd5f2015-09-30 16:50:23 +0530354 handler_fqdn += handler_list[num_handlers]->d_name;
Chris Austen54030262015-10-13 12:30:46 -0500355 printf("Registering handler:[%s]\n",handler_fqdn.c_str());
356
vishwabmcba0bd5f2015-09-30 16:50:23 +0530357 lib_handler = dlopen(handler_fqdn.c_str(), RTLD_NOW);
358 if(lib_handler == NULL)
359 {
Chris Austen120f7322015-10-14 23:27:31 -0500360 fprintf(stderr,"ERROR opening [%s]: %s\n",
361 handler_fqdn.c_str(), dlerror());
vishwabmcba0bd5f2015-09-30 16:50:23 +0530362 }
363 // Wipe the memory allocated for this particular entry.
364 free(handler_list[num_handlers]);
365 }
366 // Done with all registration.
367 free(handler_list);
368 }
369
370 // TODO : What to be done on the memory that is given by dlopen ?.
371 return;
372}
373
Chris Austen30195fa2015-11-13 14:39:19 -0600374sd_bus *ipmid_get_sd_bus_connection(void) {
375 return bus;
376}
377
vishwab9f559a2016-01-13 01:53:08 -0600378sd_bus_slot *ipmid_get_sd_bus_slot(void) {
379 return ipmid_slot;
380}
381
vishwabmcba0bd5f2015-09-30 16:50:23 +0530382int main(int argc, char *argv[])
383{
Chris Austen0ba649e2015-10-13 12:28:13 -0500384 int r;
Chris Austen99497312015-10-22 13:00:16 -0500385 unsigned long tvalue;
386 int c;
387
388
389
390 // This file and subsequient switch is for turning on levels
391 // of trace
392 ipmicmddetails = ipmiio = ipmidbus = fopen("/dev/null", "w");
393
394 while ((c = getopt (argc, argv, "h:d:")) != -1)
395 switch (c) {
396 case 'd':
397 tvalue = strtoul(optarg, NULL, 16);
398 if (1&tvalue) {
399 ipmiio = stdout;
400 }
401 if (2&tvalue) {
402 ipmidbus = stdout;
403 }
404 if (4&tvalue) {
405 ipmicmddetails = stdout;
406 }
407 break;
408 case 'h':
409 case '?':
410 print_usage();
411 return 1;
412 }
Chris Austen0ba649e2015-10-13 12:28:13 -0500413
414
Chris Austen0ba649e2015-10-13 12:28:13 -0500415 /* Connect to system bus */
416 r = sd_bus_open_system(&bus);
417 if (r < 0) {
418 fprintf(stderr, "Failed to connect to system bus: %s\n",
419 strerror(-r));
420 goto finish;
421 }
vishwabmcba0bd5f2015-09-30 16:50:23 +0530422
Chris Austen30195fa2015-11-13 14:39:19 -0600423 // Register all the handlers that provider implementation to IPMI commands.
424 ipmi_register_callback_handlers(HOST_IPMI_LIB_PATH);
425
vishwa36993272015-11-20 12:43:49 -0600426 // Watch for BT messages
vishwab9f559a2016-01-13 01:53:08 -0600427 r = sd_bus_add_match(bus, &ipmid_slot, FILTER, handle_ipmi_command, NULL);
Chris Austen0ba649e2015-10-13 12:28:13 -0500428 if (r < 0) {
429 fprintf(stderr, "Failed: sd_bus_add_match: %s : %s\n", strerror(-r), FILTER);
430 goto finish;
431 }
vishwabmcba0bd5f2015-09-30 16:50:23 +0530432
vishwabmcba0bd5f2015-09-30 16:50:23 +0530433
Chris Austen0ba649e2015-10-13 12:28:13 -0500434 for (;;) {
435 /* Process requests */
Chris Austen0ba649e2015-10-13 12:28:13 -0500436 r = sd_bus_process(bus, NULL);
437 if (r < 0) {
438 fprintf(stderr, "Failed to process bus: %s\n", strerror(-r));
439 goto finish;
440 }
441 if (r > 0) {
442 continue;
443 }
444
445 r = sd_bus_wait(bus, (uint64_t) - 1);
446 if (r < 0) {
447 fprintf(stderr, "Failed to wait on bus: %s\n", strerror(-r));
448 goto finish;
449 }
450 }
451
452finish:
vishwab9f559a2016-01-13 01:53:08 -0600453 sd_bus_slot_unref(ipmid_slot);
Chris Austen0ba649e2015-10-13 12:28:13 -0500454 sd_bus_unref(bus);
455 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
456
vishwabmcba0bd5f2015-09-30 16:50:23 +0530457}
Chris Austenb071c702015-10-15 00:00:09 -0500458
Chris Austen0012e9b2015-10-22 01:37:46 -0500459// Use a lookup table to find the interface name of a specific sensor
460// This will be used until an alternative is found. this is the first
461// step for mapping IPMI
462int find_interface_property_fru_type(dbus_interface_t *interface, const char *property_name, char *property_value) {
Chris Austenb071c702015-10-15 00:00:09 -0500463
Joel Stanleyf19539e2015-11-25 17:24:05 +1030464 char *str1;
Chris Austen0012e9b2015-10-22 01:37:46 -0500465 sd_bus_error error = SD_BUS_ERROR_NULL;
466 sd_bus_message *reply = NULL, *m=NULL;
Chris Austenb071c702015-10-15 00:00:09 -0500467
468
Chris Austen0012e9b2015-10-22 01:37:46 -0500469 int r;
470
Chris Austen0012e9b2015-10-22 01:37:46 -0500471 r = sd_bus_message_new_method_call(bus,&m,interface->bus,interface->path,"org.freedesktop.DBus.Properties","Get");
472 if (r < 0) {
473 fprintf(stderr, "Failed to create a method call: %s", strerror(-r));
474 fprintf(stderr,"Bus: %s Path: %s Interface: %s \n",
475 interface->bus, interface->path, interface->interface);
vishwa1eaea4f2016-02-26 11:57:40 -0600476 goto final;
Chris Austen0012e9b2015-10-22 01:37:46 -0500477 }
478
479 r = sd_bus_message_append(m, "ss", "org.openbmc.InventoryItem", property_name);
480 if (r < 0) {
481 fprintf(stderr, "Failed to create a input parameter: %s", strerror(-r));
482 fprintf(stderr,"Bus: %s Path: %s Interface: %s \n",
483 interface->bus, interface->path, interface->interface);
vishwa1eaea4f2016-02-26 11:57:40 -0600484 goto final;
Chris Austen0012e9b2015-10-22 01:37:46 -0500485 }
486
487 r = sd_bus_call(bus, m, 0, &error, &reply);
488 if (r < 0) {
489 fprintf(stderr, "Failed to call the method: %s", strerror(-r));
490 goto final;
491 }
492
493 r = sd_bus_message_read(reply, "v", "s", &str1) ;
494 if (r < 0) {
495 fprintf(stderr, "Failed to get a response: %s", strerror(-r));
496 goto final;
497 }
498
499 strcpy(property_value, str1);
500
501final:
502
503 sd_bus_error_free(&error);
vishwa1eaea4f2016-02-26 11:57:40 -0600504 m = sd_bus_message_unref(m);
505 reply = sd_bus_message_unref(reply);
Chris Austen0012e9b2015-10-22 01:37:46 -0500506
507 return r;
508}
Chris Austenb071c702015-10-15 00:00:09 -0500509
Chris Austen41a4b312015-10-25 03:45:42 -0500510
Chris Austenb071c702015-10-15 00:00:09 -0500511// Use a lookup table to find the interface name of a specific sensor
512// This will be used until an alternative is found. this is the first
513// step for mapping IPMI
514int find_openbmc_path(const char *type, const uint8_t num, dbus_interface_t *interface) {
515
516 const char *busname = "org.openbmc.managers.System";
517 const char *objname = "/org/openbmc/managers/System";
518
519 char *str1, *str2, *str3;
520 sd_bus_error error = SD_BUS_ERROR_NULL;
vishwa1eaea4f2016-02-26 11:57:40 -0600521 sd_bus_message *reply = NULL;
Chris Austenb071c702015-10-15 00:00:09 -0500522
523
524 int r;
525
vishwa1eaea4f2016-02-26 11:57:40 -0600526 r = sd_bus_call_method(bus,busname,objname,busname, "getObjectFromByteId",
527 &error, &reply, "sy", type, num);
Chris Austenb071c702015-10-15 00:00:09 -0500528 if (r < 0) {
529 fprintf(stderr, "Failed to create a method call: %s", strerror(-r));
Chris Austenb071c702015-10-15 00:00:09 -0500530 goto final;
531 }
532
Chris Austenb071c702015-10-15 00:00:09 -0500533 r = sd_bus_message_read(reply, "(sss)", &str1, &str2, &str3);
534 if (r < 0) {
535 fprintf(stderr, "Failed to get a response: %s", strerror(-r));
536 goto final;
537 }
538
539 strncpy(interface->bus, str1, MAX_DBUS_PATH);
540 strncpy(interface->path, str2, MAX_DBUS_PATH);
541 strncpy(interface->interface, str3, MAX_DBUS_PATH);
542
543 interface->sensornumber = num;
544
Chris Austenb071c702015-10-15 00:00:09 -0500545final:
546
547 sd_bus_error_free(&error);
vishwa1eaea4f2016-02-26 11:57:40 -0600548 reply = sd_bus_message_unref(reply);
Chris Austenb071c702015-10-15 00:00:09 -0500549
550 return r;
551}
552
553
554/////////////////////////////////////////////////////////////////////
555//
556// Routines used by ipmi commands wanting to interact on the dbus
557//
558/////////////////////////////////////////////////////////////////////
Chris Austen10ccc0f2015-12-10 18:27:04 -0600559int set_sensor_dbus_state_s(uint8_t number, const char *method, const char *value) {
Chris Austen0130d6e2015-10-15 22:32:36 -0500560
561
562 dbus_interface_t a;
563 int r;
564 sd_bus_error error = SD_BUS_ERROR_NULL;
Joel Stanleyf19539e2015-11-25 17:24:05 +1030565 sd_bus_message *m=NULL;
Chris Austen0130d6e2015-10-15 22:32:36 -0500566
Chris Austen99497312015-10-22 13:00:16 -0500567 fprintf(ipmidbus, "Attempting to set a dbus Variant Sensor 0x%02x via %s with a value of %s\n",
Chris Austen0130d6e2015-10-15 22:32:36 -0500568 number, method, value);
569
570 r = find_openbmc_path("SENSOR", number, &a);
571
Chris Austen0130d6e2015-10-15 22:32:36 -0500572 r = sd_bus_message_new_method_call(bus,&m,a.bus,a.path,a.interface,method);
573 if (r < 0) {
574 fprintf(stderr, "Failed to create a method call: %s", strerror(-r));
vishwa1eaea4f2016-02-26 11:57:40 -0600575 goto final;
Chris Austen0130d6e2015-10-15 22:32:36 -0500576 }
577
578 r = sd_bus_message_append(m, "v", "s", value);
579 if (r < 0) {
580 fprintf(stderr, "Failed to create a input parameter: %s", strerror(-r));
vishwa1eaea4f2016-02-26 11:57:40 -0600581 goto final;
Chris Austen0130d6e2015-10-15 22:32:36 -0500582 }
583
584
Chris Austen0130d6e2015-10-15 22:32:36 -0500585 r = sd_bus_call(bus, m, 0, &error, NULL);
586 if (r < 0) {
Chris Austen10ccc0f2015-12-10 18:27:04 -0600587 fprintf(stderr, "Failed to call the method: %s", strerror(-r));
Chris Austen0130d6e2015-10-15 22:32:36 -0500588 }
589
vishwa1eaea4f2016-02-26 11:57:40 -0600590final:
Chris Austen0130d6e2015-10-15 22:32:36 -0500591 sd_bus_error_free(&error);
vishwa1eaea4f2016-02-26 11:57:40 -0600592 m = sd_bus_message_unref(m);
Chris Austen0130d6e2015-10-15 22:32:36 -0500593
594 return 0;
595}
Chris Austen10ccc0f2015-12-10 18:27:04 -0600596int set_sensor_dbus_state_y(uint8_t number, const char *method, const uint8_t value) {
597
598
599 dbus_interface_t a;
600 int r;
601 sd_bus_error error = SD_BUS_ERROR_NULL;
602 sd_bus_message *m=NULL;
603
604 fprintf(ipmidbus, "Attempting to set a dbus Variant Sensor 0x%02x via %s with a value of 0x%02x\n",
605 number, method, value);
606
607 r = find_openbmc_path("SENSOR", number, &a);
608
609 r = sd_bus_message_new_method_call(bus,&m,a.bus,a.path,a.interface,method);
610 if (r < 0) {
611 fprintf(stderr, "Failed to create a method call: %s", strerror(-r));
vishwa1eaea4f2016-02-26 11:57:40 -0600612 goto final;
Chris Austen10ccc0f2015-12-10 18:27:04 -0600613 }
614
Adriana Kobylak93125982016-03-01 12:48:10 -0600615 r = sd_bus_message_append(m, "v", "i", value);
Chris Austen10ccc0f2015-12-10 18:27:04 -0600616 if (r < 0) {
617 fprintf(stderr, "Failed to create a input parameter: %s", strerror(-r));
vishwa1eaea4f2016-02-26 11:57:40 -0600618 goto final;
Chris Austen10ccc0f2015-12-10 18:27:04 -0600619 }
620
621
622 r = sd_bus_call(bus, m, 0, &error, NULL);
623 if (r < 0) {
624 fprintf(stderr, "12 Failed to call the method: %s", strerror(-r));
625 }
626
vishwa1eaea4f2016-02-26 11:57:40 -0600627final:
Chris Austen10ccc0f2015-12-10 18:27:04 -0600628 sd_bus_error_free(&error);
vishwa1eaea4f2016-02-26 11:57:40 -0600629 m = sd_bus_message_unref(m);
Chris Austen10ccc0f2015-12-10 18:27:04 -0600630
631 return 0;
vishwa1eaea4f2016-02-26 11:57:40 -0600632}