blob: 960f5dc67aafeb1511a915f3aab306dd6053ea40 [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
Jeremy Kerre41081f2015-10-27 12:11:36 +080029const char * DBUS_INTF = "org.openbmc.HostIpmi";
vishwabmcba0bd5f2015-09-30 16:50:23 +053030
Jeremy Kerre41081f2015-10-27 12:11:36 +080031const char * FILTER = "type='signal',interface='org.openbmc.HostIpmi',member='ReceivedMessage'";
Chris Austen0ba649e2015-10-13 12:28:13 -050032
33
vishwabmcba0bd5f2015-09-30 16:50:23 +053034typedef std::pair<ipmi_netfn_t, ipmi_cmd_t> ipmi_fn_cmd_t;
35typedef std::pair<ipmid_callback_t, ipmi_context_t> ipmi_fn_context_t;
36
37// Global data structure that contains the IPMI command handler's registrations.
38std::map<ipmi_fn_cmd_t, ipmi_fn_context_t> g_ipmid_router_map;
39
Nan Li36c0cb62016-03-31 11:16:08 +080040// IPMI Spec, shared Reservation ID.
41unsigned short g_sel_reserve = 0xFFFF;
42
43unsigned short get_sel_reserve_id(void)
44{
45 return g_sel_reserve;
46}
Chris Austen0ba649e2015-10-13 12:28:13 -050047
Chris Austen0ba649e2015-10-13 12:28:13 -050048#ifndef HEXDUMP_COLS
49#define HEXDUMP_COLS 16
50#endif
51
Chris Austen99497312015-10-22 13:00:16 -050052void hexdump(FILE *s, void *mem, size_t len)
Chris Austen0ba649e2015-10-13 12:28:13 -050053{
54 unsigned int i, j;
Chris Austen120f7322015-10-14 23:27:31 -050055
Chris Austen0ba649e2015-10-13 12:28:13 -050056 for(i = 0; i < len + ((len % HEXDUMP_COLS) ? (HEXDUMP_COLS - len % HEXDUMP_COLS) : 0); i++)
57 {
58 /* print offset */
59 if(i % HEXDUMP_COLS == 0)
60 {
Chris Austen99497312015-10-22 13:00:16 -050061 fprintf(s,"0x%06x: ", i);
Chris Austen0ba649e2015-10-13 12:28:13 -050062 }
Chris Austen120f7322015-10-14 23:27:31 -050063
Chris Austen0ba649e2015-10-13 12:28:13 -050064 /* print hex data */
65 if(i < len)
66 {
Chris Austen99497312015-10-22 13:00:16 -050067 fprintf(s,"%02x ", 0xFF & ((char*)mem)[i]);
Chris Austen0ba649e2015-10-13 12:28:13 -050068 }
69 else /* end of block, just aligning for ASCII dump */
70 {
Chris Austen99497312015-10-22 13:00:16 -050071 fprintf(s," ");
Chris Austen0ba649e2015-10-13 12:28:13 -050072 }
Chris Austen120f7322015-10-14 23:27:31 -050073
Chris Austen0ba649e2015-10-13 12:28:13 -050074 /* print ASCII dump */
75 if(i % HEXDUMP_COLS == (HEXDUMP_COLS - 1))
76 {
77 for(j = i - (HEXDUMP_COLS - 1); j <= i; j++)
78 {
79 if(j >= len) /* end of block, not really printing */
80 {
Chris Austen99497312015-10-22 13:00:16 -050081 fputc(' ', s);
Chris Austen0ba649e2015-10-13 12:28:13 -050082 }
83 else if(isprint(((char*)mem)[j])) /* printable char */
84 {
Chris Austen99497312015-10-22 13:00:16 -050085 fputc(0xFF & ((char*)mem)[j], s);
Chris Austen0ba649e2015-10-13 12:28:13 -050086 }
87 else /* other char */
88 {
Chris Austen99497312015-10-22 13:00:16 -050089 fputc('.',s);
Chris Austen0ba649e2015-10-13 12:28:13 -050090 }
91 }
Chris Austen99497312015-10-22 13:00:16 -050092 fputc('\n',s);
Chris Austen0ba649e2015-10-13 12:28:13 -050093 }
94 }
95}
96
97
vishwabmcba0bd5f2015-09-30 16:50:23 +053098// Method that gets called by shared libraries to get their command handlers registered
99void ipmi_register_callback(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
100 ipmi_context_t context, ipmid_callback_t handler)
101{
102 // Pack NetFn and Command in one.
103 auto netfn_and_cmd = std::make_pair(netfn, cmd);
104
105 // Pack Function handler and Data in another.
106 auto handler_and_context = std::make_pair(handler, context);
107
108 // Check if the registration has already been made..
109 auto iter = g_ipmid_router_map.find(netfn_and_cmd);
110 if(iter != g_ipmid_router_map.end())
111 {
112 fprintf(stderr,"ERROR : Duplicate registration for NetFn [0x%X], Cmd:[0x%X]\n",netfn, cmd);
113 }
114 else
115 {
116 // This is a fresh registration.. Add it to the map.
117 g_ipmid_router_map.emplace(netfn_and_cmd, handler_and_context);
118 }
119
120 return;
121}
122
123// Looks at the map and calls corresponding handler functions.
124ipmi_ret_t ipmi_netfn_router(ipmi_netfn_t netfn, ipmi_cmd_t cmd, ipmi_request_t request,
125 ipmi_response_t response, ipmi_data_len_t data_len)
126{
127 // return from the Command handlers.
128 ipmi_ret_t rc = IPMI_CC_INVALID;
129
130 // Walk the map that has the registered handlers and invoke the approprite
131 // handlers for matching commands.
132 auto iter = g_ipmid_router_map.find(std::make_pair(netfn, cmd));
133 if(iter == g_ipmid_router_map.end())
134 {
Chris Austen99497312015-10-22 13:00:16 -0500135 fprintf(stderr, "No registered handlers for NetFn:[0x%X], Cmd:[0x%X]"
vishwabmcba0bd5f2015-09-30 16:50:23 +0530136 " trying Wilcard implementation \n",netfn, cmd);
137
138 // Now that we did not find any specific [NetFn,Cmd], tuple, check for
139 // NetFn, WildCard command present.
140 iter = g_ipmid_router_map.find(std::make_pair(netfn, IPMI_CMD_WILDCARD));
141 if(iter == g_ipmid_router_map.end())
142 {
Chris Austen99497312015-10-22 13:00:16 -0500143 fprintf(stderr, "No Registered handlers for NetFn:[0x%X],Cmd:[0x%X]\n",netfn, IPMI_CMD_WILDCARD);
vishwabmcba0bd5f2015-09-30 16:50:23 +0530144
145 // Respond with a 0xC1
146 memcpy(response, &rc, IPMI_CC_LEN);
147 *data_len = IPMI_CC_LEN;
148 return rc;
149 }
150 }
151
152#ifdef __IPMI_DEBUG__
153 // We have either a perfect match -OR- a wild card atleast,
154 printf("Calling Net function:[0x%X], Command:[0x%X]\n", netfn, cmd);
155#endif
156
157 // Extract the map data onto appropriate containers
158 auto handler_and_context = iter->second;
159
160 // Creating a pointer type casted to char* to make sure we advance 1 byte
161 // when we advance pointer to next's address. advancing void * would not
162 // make sense.
163 char *respo = &((char *)response)[IPMI_CC_LEN];
164
165 // Response message from the plugin goes into a byte post the base response
166 rc = (handler_and_context.first) (netfn, cmd, request, respo,
167 data_len, handler_and_context.second);
Chris Austen120f7322015-10-14 23:27:31 -0500168
vishwabmcba0bd5f2015-09-30 16:50:23 +0530169 // Now copy the return code that we got from handler and pack it in first
170 // byte.
171 memcpy(response, &rc, IPMI_CC_LEN);
Chris Austen120f7322015-10-14 23:27:31 -0500172
vishwabmcba0bd5f2015-09-30 16:50:23 +0530173 // Data length is now actual data + completion code.
174 *data_len = *data_len + IPMI_CC_LEN;
175
176 return rc;
177}
178
vishwabmcba0bd5f2015-09-30 16:50:23 +0530179
vishwabmcba0bd5f2015-09-30 16:50:23 +0530180
vishwabmcba0bd5f2015-09-30 16:50:23 +0530181
Jeremy Kerr2564b1a2015-10-27 13:37:17 +0800182static 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 +0530183
Chris Austen0ba649e2015-10-13 12:28:13 -0500184 sd_bus_error error = SD_BUS_ERROR_NULL;
185 sd_bus_message *reply = NULL, *m=NULL;
Jeremy Kerre41081f2015-10-27 12:11:36 +0800186 const char *dest, *path;
Chris Austen0ba649e2015-10-13 12:28:13 -0500187 int r, pty;
vishwabmcba0bd5f2015-09-30 16:50:23 +0530188
Jeremy Kerre41081f2015-10-27 12:11:36 +0800189 dest = sd_bus_message_get_sender(req);
190 path = sd_bus_message_get_path(req);
vishwabmcba0bd5f2015-09-30 16:50:23 +0530191
Jeremy Kerre41081f2015-10-27 12:11:36 +0800192 r = sd_bus_message_new_method_call(bus,&m,dest,path,DBUS_INTF,"sendMessage");
Chris Austen0ba649e2015-10-13 12:28:13 -0500193 if (r < 0) {
194 fprintf(stderr, "Failed to add the method object: %s\n", strerror(-r));
195 return -1;
vishwabmcba0bd5f2015-09-30 16:50:23 +0530196 }
197
vishwabmcba0bd5f2015-09-30 16:50:23 +0530198
Chris Austenabfb5e82015-10-13 12:29:24 -0500199 // Responses in IPMI require a bit set. So there ya go...
Jeremy Kerr2564b1a2015-10-27 13:37:17 +0800200 netfn |= 0x01;
vishwabmcba0bd5f2015-09-30 16:50:23 +0530201
Chris Austen0ba649e2015-10-13 12:28:13 -0500202
203 // Add the bytes needed for the methods to be called
Jeremy Kerr2564b1a2015-10-27 13:37:17 +0800204 r = sd_bus_message_append(m, "yyyyy", seq, netfn, lun, cmd, cc);
Chris Austen0ba649e2015-10-13 12:28:13 -0500205 if (r < 0) {
206 fprintf(stderr, "Failed add the netfn and others : %s\n", strerror(-r));
Chris Austen169395e2015-12-02 20:56:15 -0600207 goto final;
Chris Austen0ba649e2015-10-13 12:28:13 -0500208 }
Chris Austen120f7322015-10-14 23:27:31 -0500209
Chris Austen0ba649e2015-10-13 12:28:13 -0500210 r = sd_bus_message_append_array(m, 'y', buf, len);
211 if (r < 0) {
212 fprintf(stderr, "Failed to add the string of response bytes: %s\n", strerror(-r));
Chris Austen169395e2015-12-02 20:56:15 -0600213 goto final;
Chris Austen0ba649e2015-10-13 12:28:13 -0500214 }
215
216
217
218 // Call the IPMI responder on the bus so the message can be sent to the CEC
219 r = sd_bus_call(bus, m, 0, &error, &reply);
220 if (r < 0) {
Chris Austen169395e2015-12-02 20:56:15 -0600221 fprintf(stderr, "Failed to call the method: %s\n", strerror(-r));
Chris Austen6bd23962015-12-07 21:31:48 -0600222 fprintf(stderr, "Dest: %s, Path: %s\n", dest, path);
Chris Austen169395e2015-12-02 20:56:15 -0600223 goto final;
Chris Austen0ba649e2015-10-13 12:28:13 -0500224 }
225
226 r = sd_bus_message_read(reply, "x", &pty);
Chris Austen0ba649e2015-10-13 12:28:13 -0500227 if (r < 0) {
228 fprintf(stderr, "Failed to get a rc from the method: %s\n", strerror(-r));
Chris Austen0ba649e2015-10-13 12:28:13 -0500229 }
230
Chris Austen169395e2015-12-02 20:56:15 -0600231final:
Chris Austen0ba649e2015-10-13 12:28:13 -0500232 sd_bus_error_free(&error);
vishwa1eaea4f2016-02-26 11:57:40 -0600233 m = sd_bus_message_unref(m);
234 reply = sd_bus_message_unref(reply);
Chris Austen0ba649e2015-10-13 12:28:13 -0500235
Chris Austen0ba649e2015-10-13 12:28:13 -0500236 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
Chris Austen0ba649e2015-10-13 12:28:13 -0500237}
238
239static int handle_ipmi_command(sd_bus_message *m, void *user_data, sd_bus_error
240 *ret_error) {
241 int r = 0;
Jeremy Kerr2564b1a2015-10-27 13:37:17 +0800242 unsigned char sequence, netfn, lun, cmd;
Chris Austen0ba649e2015-10-13 12:28:13 -0500243 const void *request;
244 size_t sz;
245 size_t resplen =MAX_IPMI_BUFFER;
246 unsigned char response[MAX_IPMI_BUFFER];
247
Chris Austen0ba649e2015-10-13 12:28:13 -0500248 memset(response, 0, MAX_IPMI_BUFFER);
249
Jeremy Kerr2564b1a2015-10-27 13:37:17 +0800250 r = sd_bus_message_read(m, "yyyy", &sequence, &netfn, &lun, &cmd);
Chris Austen0ba649e2015-10-13 12:28:13 -0500251 if (r < 0) {
252 fprintf(stderr, "Failed to parse signal message: %s\n", strerror(-r));
253 return -1;
254 }
255
256 r = sd_bus_message_read_array(m, 'y', &request, &sz );
257 if (r < 0) {
258 fprintf(stderr, "Failed to parse signal message: %s\n", strerror(-r));
259 return -1;
260 }
261
Chris Austen99497312015-10-22 13:00:16 -0500262 fprintf(ipmiio, "IPMI Incoming: Seq 0x%02x, NetFn 0x%02x, CMD: 0x%02x \n", sequence, netfn, cmd);
263 hexdump(ipmiio, (void*)request, sz);
Chris Austen0ba649e2015-10-13 12:28:13 -0500264
Chris Austen120f7322015-10-14 23:27:31 -0500265 // Allow the length field to be used for both input and output of the
Chris Austen0ba649e2015-10-13 12:28:13 -0500266 // ipmi call
267 resplen = sz;
268
Chris Austen120f7322015-10-14 23:27:31 -0500269 // Now that we have parsed the entire byte array from the caller
vishwabmcba0bd5f2015-09-30 16:50:23 +0530270 // we can call the ipmi router to do the work...
Chris Austen0ba649e2015-10-13 12:28:13 -0500271 r = ipmi_netfn_router(netfn, cmd, (void *)request, (void *)response, &resplen);
272 if(r != 0)
vishwabmcba0bd5f2015-09-30 16:50:23 +0530273 {
Chris Austen0ba649e2015-10-13 12:28:13 -0500274 fprintf(stderr,"ERROR:[0x%X] handling NetFn:[0x%X], Cmd:[0x%X]\n",r, netfn, cmd);
Nan Li80be4b92016-05-23 19:30:49 +0800275
tomjose7ec0add2016-06-27 07:59:28 -0500276 if(r < 0) {
Nan Li80be4b92016-05-23 19:30:49 +0800277 response[0] = IPMI_CC_UNSPECIFIED_ERROR;
278 }
vishwabmcba0bd5f2015-09-30 16:50:23 +0530279 }
280
Chris Austen99497312015-10-22 13:00:16 -0500281 fprintf(ipmiio, "IPMI Response:\n");
282 hexdump(ipmiio, (void*)response, resplen);
vishwabmcba0bd5f2015-09-30 16:50:23 +0530283
Chris Austen0ba649e2015-10-13 12:28:13 -0500284 // Send the response buffer from the ipmi command
Jeremy Kerr2564b1a2015-10-27 13:37:17 +0800285 r = send_ipmi_message(m, sequence, netfn, lun, cmd, response[0],
286 ((unsigned char *)response) + 1, resplen - 1);
Chris Austen0ba649e2015-10-13 12:28:13 -0500287 if (r < 0) {
288 fprintf(stderr, "Failed to send the response message\n");
289 return -1;
vishwabmcba0bd5f2015-09-30 16:50:23 +0530290 }
291
vishwabmcba0bd5f2015-09-30 16:50:23 +0530292
Chris Austen0ba649e2015-10-13 12:28:13 -0500293 return 0;
vishwabmcba0bd5f2015-09-30 16:50:23 +0530294}
295
Chris Austen0ba649e2015-10-13 12:28:13 -0500296
vishwabmcba0bd5f2015-09-30 16:50:23 +0530297//----------------------------------------------------------------------
298// handler_select
299// Select all the files ending with with .so. in the given diretcory
300// @d: dirent structure containing the file name
301//----------------------------------------------------------------------
302int handler_select(const struct dirent *entry)
303{
304 // To hold ".so" from entry->d_name;
305 char dname_copy[4] = {0};
306
307 // We want to avoid checking for everything and isolate to the ones having
Adriana Kobylak87e080b2016-07-10 13:16:53 -0500308 // .so.* or .so in them.
309 // Check for versioned libraries .so.*
310 if(strstr(entry->d_name, IPMI_PLUGIN_SONAME_EXTN))
311 {
312 return 1;
313 }
314 // Check for non versioned libraries .so
315 else if(strstr(entry->d_name, IPMI_PLUGIN_EXTN))
vishwabmcba0bd5f2015-09-30 16:50:23 +0530316 {
317 // It is possible that .so could be anywhere in the string but unlikely
Chris Austen120f7322015-10-14 23:27:31 -0500318 // But being careful here. Get the base address of the string, move
vishwabmcba0bd5f2015-09-30 16:50:23 +0530319 // until end and come back 3 steps and that gets what we need.
320 strcpy(dname_copy, (entry->d_name + strlen(entry->d_name)-strlen(IPMI_PLUGIN_EXTN)));
321 if(strcmp(dname_copy, IPMI_PLUGIN_EXTN) == 0)
322 {
323 return 1;
324 }
325 }
326 return 0;
327}
328
329// 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 -0500330// register a callback handler
vishwabmcba0bd5f2015-09-30 16:50:23 +0530331void ipmi_register_callback_handlers(const char* ipmi_lib_path)
332{
333 // For walking the ipmi_lib_path
334 struct dirent **handler_list;
335 int num_handlers = 0;
336
337 // This is used to check and abort if someone tries to register a bad one.
338 void *lib_handler = NULL;
339
340 if(ipmi_lib_path == NULL)
341 {
342 fprintf(stderr,"ERROR; No handlers to be registered for ipmi.. Aborting\n");
343 assert(0);
344 }
345 else
346 {
347 // 1: Open ipmi_lib_path. Its usually "/usr/lib/phosphor-host-ipmid"
348 // 2: Scan the directory for the files that end with .so
Chris Austen120f7322015-10-14 23:27:31 -0500349 // 3: For each one of them, just do a 'dlopen' so that they register
vishwabmcba0bd5f2015-09-30 16:50:23 +0530350 // the handlers for callback routines.
351
352 std::string handler_fqdn = ipmi_lib_path;
Chris Austen120f7322015-10-14 23:27:31 -0500353
vishwabmcba0bd5f2015-09-30 16:50:23 +0530354 // Append a "/" since we need to add the name of the .so. If there is
355 // already a .so, adding one more is not any harm.
356 handler_fqdn += "/";
357
358 num_handlers = scandir(ipmi_lib_path, &handler_list, handler_select, alphasort);
Nan Li36c0cb62016-03-31 11:16:08 +0800359 if (num_handlers < 0)
360 return;
Jeremy Kerr5e8f85e2015-10-27 13:43:54 +0800361
vishwabmcba0bd5f2015-09-30 16:50:23 +0530362 while(num_handlers--)
363 {
Chris Austen54030262015-10-13 12:30:46 -0500364 handler_fqdn = ipmi_lib_path;
vishwabmcba0bd5f2015-09-30 16:50:23 +0530365 handler_fqdn += handler_list[num_handlers]->d_name;
Chris Austen54030262015-10-13 12:30:46 -0500366 printf("Registering handler:[%s]\n",handler_fqdn.c_str());
367
vishwabmcba0bd5f2015-09-30 16:50:23 +0530368 lib_handler = dlopen(handler_fqdn.c_str(), RTLD_NOW);
Nan Li36c0cb62016-03-31 11:16:08 +0800369
vishwabmcba0bd5f2015-09-30 16:50:23 +0530370 if(lib_handler == NULL)
371 {
Chris Austen120f7322015-10-14 23:27:31 -0500372 fprintf(stderr,"ERROR opening [%s]: %s\n",
373 handler_fqdn.c_str(), dlerror());
vishwabmcba0bd5f2015-09-30 16:50:23 +0530374 }
375 // Wipe the memory allocated for this particular entry.
376 free(handler_list[num_handlers]);
377 }
Nan Li36c0cb62016-03-31 11:16:08 +0800378
vishwabmcba0bd5f2015-09-30 16:50:23 +0530379 // Done with all registration.
380 free(handler_list);
381 }
382
383 // TODO : What to be done on the memory that is given by dlopen ?.
384 return;
385}
386
Chris Austen30195fa2015-11-13 14:39:19 -0600387sd_bus *ipmid_get_sd_bus_connection(void) {
388 return bus;
389}
390
vishwab9f559a2016-01-13 01:53:08 -0600391sd_bus_slot *ipmid_get_sd_bus_slot(void) {
392 return ipmid_slot;
393}
394
vishwabmcba0bd5f2015-09-30 16:50:23 +0530395int main(int argc, char *argv[])
396{
Chris Austen0ba649e2015-10-13 12:28:13 -0500397 int r;
Chris Austen99497312015-10-22 13:00:16 -0500398 unsigned long tvalue;
399 int c;
400
401
402
403 // This file and subsequient switch is for turning on levels
404 // of trace
405 ipmicmddetails = ipmiio = ipmidbus = fopen("/dev/null", "w");
406
407 while ((c = getopt (argc, argv, "h:d:")) != -1)
408 switch (c) {
409 case 'd':
410 tvalue = strtoul(optarg, NULL, 16);
411 if (1&tvalue) {
412 ipmiio = stdout;
413 }
414 if (2&tvalue) {
415 ipmidbus = stdout;
416 }
417 if (4&tvalue) {
418 ipmicmddetails = stdout;
419 }
420 break;
421 case 'h':
422 case '?':
423 print_usage();
424 return 1;
425 }
Chris Austen0ba649e2015-10-13 12:28:13 -0500426
427
Chris Austen0ba649e2015-10-13 12:28:13 -0500428 /* Connect to system bus */
429 r = sd_bus_open_system(&bus);
430 if (r < 0) {
431 fprintf(stderr, "Failed to connect to system bus: %s\n",
432 strerror(-r));
433 goto finish;
434 }
vishwabmcba0bd5f2015-09-30 16:50:23 +0530435
Chris Austen30195fa2015-11-13 14:39:19 -0600436 // Register all the handlers that provider implementation to IPMI commands.
437 ipmi_register_callback_handlers(HOST_IPMI_LIB_PATH);
438
vishwa36993272015-11-20 12:43:49 -0600439 // Watch for BT messages
vishwab9f559a2016-01-13 01:53:08 -0600440 r = sd_bus_add_match(bus, &ipmid_slot, FILTER, handle_ipmi_command, NULL);
Chris Austen0ba649e2015-10-13 12:28:13 -0500441 if (r < 0) {
442 fprintf(stderr, "Failed: sd_bus_add_match: %s : %s\n", strerror(-r), FILTER);
443 goto finish;
444 }
vishwabmcba0bd5f2015-09-30 16:50:23 +0530445
vishwabmcba0bd5f2015-09-30 16:50:23 +0530446
Chris Austen0ba649e2015-10-13 12:28:13 -0500447 for (;;) {
448 /* Process requests */
Chris Austen0ba649e2015-10-13 12:28:13 -0500449 r = sd_bus_process(bus, NULL);
450 if (r < 0) {
451 fprintf(stderr, "Failed to process bus: %s\n", strerror(-r));
452 goto finish;
453 }
454 if (r > 0) {
455 continue;
456 }
457
458 r = sd_bus_wait(bus, (uint64_t) - 1);
459 if (r < 0) {
460 fprintf(stderr, "Failed to wait on bus: %s\n", strerror(-r));
461 goto finish;
462 }
463 }
464
465finish:
vishwab9f559a2016-01-13 01:53:08 -0600466 sd_bus_slot_unref(ipmid_slot);
Chris Austen0ba649e2015-10-13 12:28:13 -0500467 sd_bus_unref(bus);
468 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
469
vishwabmcba0bd5f2015-09-30 16:50:23 +0530470}
Chris Austenb071c702015-10-15 00:00:09 -0500471
Chris Austen0012e9b2015-10-22 01:37:46 -0500472// Use a lookup table to find the interface name of a specific sensor
473// This will be used until an alternative is found. this is the first
474// step for mapping IPMI
475int find_interface_property_fru_type(dbus_interface_t *interface, const char *property_name, char *property_value) {
Chris Austenb071c702015-10-15 00:00:09 -0500476
Joel Stanleyf19539e2015-11-25 17:24:05 +1030477 char *str1;
Chris Austen0012e9b2015-10-22 01:37:46 -0500478 sd_bus_error error = SD_BUS_ERROR_NULL;
479 sd_bus_message *reply = NULL, *m=NULL;
Chris Austenb071c702015-10-15 00:00:09 -0500480
481
Chris Austen0012e9b2015-10-22 01:37:46 -0500482 int r;
483
Chris Austen0012e9b2015-10-22 01:37:46 -0500484 r = sd_bus_message_new_method_call(bus,&m,interface->bus,interface->path,"org.freedesktop.DBus.Properties","Get");
485 if (r < 0) {
486 fprintf(stderr, "Failed to create a method call: %s", strerror(-r));
487 fprintf(stderr,"Bus: %s Path: %s Interface: %s \n",
488 interface->bus, interface->path, interface->interface);
vishwa1eaea4f2016-02-26 11:57:40 -0600489 goto final;
Chris Austen0012e9b2015-10-22 01:37:46 -0500490 }
491
492 r = sd_bus_message_append(m, "ss", "org.openbmc.InventoryItem", property_name);
493 if (r < 0) {
494 fprintf(stderr, "Failed to create a input parameter: %s", strerror(-r));
495 fprintf(stderr,"Bus: %s Path: %s Interface: %s \n",
496 interface->bus, interface->path, interface->interface);
vishwa1eaea4f2016-02-26 11:57:40 -0600497 goto final;
Chris Austen0012e9b2015-10-22 01:37:46 -0500498 }
499
500 r = sd_bus_call(bus, m, 0, &error, &reply);
501 if (r < 0) {
502 fprintf(stderr, "Failed to call the method: %s", strerror(-r));
503 goto final;
504 }
505
506 r = sd_bus_message_read(reply, "v", "s", &str1) ;
507 if (r < 0) {
508 fprintf(stderr, "Failed to get a response: %s", strerror(-r));
509 goto final;
510 }
511
512 strcpy(property_value, str1);
513
514final:
515
516 sd_bus_error_free(&error);
vishwa1eaea4f2016-02-26 11:57:40 -0600517 m = sd_bus_message_unref(m);
518 reply = sd_bus_message_unref(reply);
Chris Austen0012e9b2015-10-22 01:37:46 -0500519
520 return r;
521}
Chris Austenb071c702015-10-15 00:00:09 -0500522
Chris Austen41a4b312015-10-25 03:45:42 -0500523
Chris Austenb071c702015-10-15 00:00:09 -0500524// Use a lookup table to find the interface name of a specific sensor
525// This will be used until an alternative is found. this is the first
526// step for mapping IPMI
527int find_openbmc_path(const char *type, const uint8_t num, dbus_interface_t *interface) {
528
529 const char *busname = "org.openbmc.managers.System";
530 const char *objname = "/org/openbmc/managers/System";
531
532 char *str1, *str2, *str3;
533 sd_bus_error error = SD_BUS_ERROR_NULL;
vishwa1eaea4f2016-02-26 11:57:40 -0600534 sd_bus_message *reply = NULL;
Chris Austenb071c702015-10-15 00:00:09 -0500535
536
537 int r;
538
vishwa1eaea4f2016-02-26 11:57:40 -0600539 r = sd_bus_call_method(bus,busname,objname,busname, "getObjectFromByteId",
540 &error, &reply, "sy", type, num);
Chris Austenb071c702015-10-15 00:00:09 -0500541 if (r < 0) {
542 fprintf(stderr, "Failed to create a method call: %s", strerror(-r));
Chris Austenb071c702015-10-15 00:00:09 -0500543 goto final;
544 }
545
Chris Austenb071c702015-10-15 00:00:09 -0500546 r = sd_bus_message_read(reply, "(sss)", &str1, &str2, &str3);
547 if (r < 0) {
548 fprintf(stderr, "Failed to get a response: %s", strerror(-r));
549 goto final;
550 }
551
552 strncpy(interface->bus, str1, MAX_DBUS_PATH);
553 strncpy(interface->path, str2, MAX_DBUS_PATH);
554 strncpy(interface->interface, str3, MAX_DBUS_PATH);
555
556 interface->sensornumber = num;
557
Chris Austenb071c702015-10-15 00:00:09 -0500558final:
559
560 sd_bus_error_free(&error);
vishwa1eaea4f2016-02-26 11:57:40 -0600561 reply = sd_bus_message_unref(reply);
Chris Austenb071c702015-10-15 00:00:09 -0500562
563 return r;
564}
565
566
567/////////////////////////////////////////////////////////////////////
568//
569// Routines used by ipmi commands wanting to interact on the dbus
570//
571/////////////////////////////////////////////////////////////////////
Chris Austen10ccc0f2015-12-10 18:27:04 -0600572int set_sensor_dbus_state_s(uint8_t number, const char *method, const char *value) {
Chris Austen0130d6e2015-10-15 22:32:36 -0500573
574
575 dbus_interface_t a;
576 int r;
577 sd_bus_error error = SD_BUS_ERROR_NULL;
Joel Stanleyf19539e2015-11-25 17:24:05 +1030578 sd_bus_message *m=NULL;
Chris Austen0130d6e2015-10-15 22:32:36 -0500579
Chris Austen99497312015-10-22 13:00:16 -0500580 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 -0500581 number, method, value);
582
583 r = find_openbmc_path("SENSOR", number, &a);
584
Nan Li36deb762016-05-12 10:23:41 +0800585 if (r < 0) {
586 fprintf(stderr, "Failed to find Sensor 0x%02x\n", number);
587 return 0;
588 }
589
Chris Austen0130d6e2015-10-15 22:32:36 -0500590 r = sd_bus_message_new_method_call(bus,&m,a.bus,a.path,a.interface,method);
591 if (r < 0) {
592 fprintf(stderr, "Failed to create a method call: %s", strerror(-r));
vishwa1eaea4f2016-02-26 11:57:40 -0600593 goto final;
Chris Austen0130d6e2015-10-15 22:32:36 -0500594 }
595
596 r = sd_bus_message_append(m, "v", "s", value);
597 if (r < 0) {
598 fprintf(stderr, "Failed to create a input parameter: %s", strerror(-r));
vishwa1eaea4f2016-02-26 11:57:40 -0600599 goto final;
Chris Austen0130d6e2015-10-15 22:32:36 -0500600 }
601
602
Chris Austen0130d6e2015-10-15 22:32:36 -0500603 r = sd_bus_call(bus, m, 0, &error, NULL);
604 if (r < 0) {
Chris Austen10ccc0f2015-12-10 18:27:04 -0600605 fprintf(stderr, "Failed to call the method: %s", strerror(-r));
Chris Austen0130d6e2015-10-15 22:32:36 -0500606 }
607
vishwa1eaea4f2016-02-26 11:57:40 -0600608final:
Chris Austen0130d6e2015-10-15 22:32:36 -0500609 sd_bus_error_free(&error);
vishwa1eaea4f2016-02-26 11:57:40 -0600610 m = sd_bus_message_unref(m);
Chris Austen0130d6e2015-10-15 22:32:36 -0500611
612 return 0;
613}
Chris Austen10ccc0f2015-12-10 18:27:04 -0600614int set_sensor_dbus_state_y(uint8_t number, const char *method, const uint8_t value) {
615
616
617 dbus_interface_t a;
618 int r;
619 sd_bus_error error = SD_BUS_ERROR_NULL;
620 sd_bus_message *m=NULL;
621
622 fprintf(ipmidbus, "Attempting to set a dbus Variant Sensor 0x%02x via %s with a value of 0x%02x\n",
623 number, method, value);
624
625 r = find_openbmc_path("SENSOR", number, &a);
626
Nan Li36deb762016-05-12 10:23:41 +0800627 if (r < 0) {
628 fprintf(stderr, "Failed to find Sensor 0x%02x\n", number);
629 return 0;
630 }
631
Chris Austen10ccc0f2015-12-10 18:27:04 -0600632 r = sd_bus_message_new_method_call(bus,&m,a.bus,a.path,a.interface,method);
633 if (r < 0) {
634 fprintf(stderr, "Failed to create a method call: %s", strerror(-r));
vishwa1eaea4f2016-02-26 11:57:40 -0600635 goto final;
Chris Austen10ccc0f2015-12-10 18:27:04 -0600636 }
637
Adriana Kobylak93125982016-03-01 12:48:10 -0600638 r = sd_bus_message_append(m, "v", "i", value);
Chris Austen10ccc0f2015-12-10 18:27:04 -0600639 if (r < 0) {
640 fprintf(stderr, "Failed to create a input parameter: %s", strerror(-r));
vishwa1eaea4f2016-02-26 11:57:40 -0600641 goto final;
Chris Austen10ccc0f2015-12-10 18:27:04 -0600642 }
643
644
645 r = sd_bus_call(bus, m, 0, &error, NULL);
646 if (r < 0) {
647 fprintf(stderr, "12 Failed to call the method: %s", strerror(-r));
648 }
649
vishwa1eaea4f2016-02-26 11:57:40 -0600650final:
Chris Austen10ccc0f2015-12-10 18:27:04 -0600651 sd_bus_error_free(&error);
vishwa1eaea4f2016-02-26 11:57:40 -0600652 m = sd_bus_message_unref(m);
Chris Austen10ccc0f2015-12-10 18:27:04 -0600653
654 return 0;
vishwa1eaea4f2016-02-26 11:57:40 -0600655}