blob: 95904486e685885eaf8e235ef2cf6b1e9a7b5573 [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>
Brad Bishop35518682016-07-22 08:35:41 -040014#include <mapper.h>
Chris Austen0012e9b2015-10-22 01:37:46 -050015#include "sensorhandler.h"
Chris Austen0ba649e2015-10-13 12:28:13 -050016
Chris Austen0ba649e2015-10-13 12:28:13 -050017sd_bus *bus = NULL;
vishwab9f559a2016-01-13 01:53:08 -060018sd_bus_slot *ipmid_slot = NULL;
Chris Austen30195fa2015-11-13 14:39:19 -060019
Chris Austen41a4b312015-10-25 03:45:42 -050020FILE *ipmiio, *ipmidbus, *ipmicmddetails;
vishwabmcba0bd5f2015-09-30 16:50:23 +053021
Chris Austen99497312015-10-22 13:00:16 -050022void print_usage(void) {
23 fprintf(stderr, "Options: [-d mask]\n");
24 fprintf(stderr, " mask : 0x01 - Print ipmi packets\n");
25 fprintf(stderr, " mask : 0x02 - Print DBUS operations\n");
26 fprintf(stderr, " mask : 0x04 - Print ipmi command details\n");
27 fprintf(stderr, " mask : 0xFF - Print all trace\n");
28}
29
Jeremy Kerre41081f2015-10-27 12:11:36 +080030const char * DBUS_INTF = "org.openbmc.HostIpmi";
vishwabmcba0bd5f2015-09-30 16:50:23 +053031
Jeremy Kerre41081f2015-10-27 12:11:36 +080032const char * FILTER = "type='signal',interface='org.openbmc.HostIpmi',member='ReceivedMessage'";
Chris Austen0ba649e2015-10-13 12:28:13 -050033
34
vishwabmcba0bd5f2015-09-30 16:50:23 +053035typedef std::pair<ipmi_netfn_t, ipmi_cmd_t> ipmi_fn_cmd_t;
36typedef std::pair<ipmid_callback_t, ipmi_context_t> ipmi_fn_context_t;
37
38// Global data structure that contains the IPMI command handler's registrations.
39std::map<ipmi_fn_cmd_t, ipmi_fn_context_t> g_ipmid_router_map;
40
Nan Li36c0cb62016-03-31 11:16:08 +080041// IPMI Spec, shared Reservation ID.
42unsigned short g_sel_reserve = 0xFFFF;
43
44unsigned short get_sel_reserve_id(void)
45{
46 return g_sel_reserve;
47}
Chris Austen0ba649e2015-10-13 12:28:13 -050048
Chris Austen0ba649e2015-10-13 12:28:13 -050049#ifndef HEXDUMP_COLS
50#define HEXDUMP_COLS 16
51#endif
52
Chris Austen99497312015-10-22 13:00:16 -050053void hexdump(FILE *s, void *mem, size_t len)
Chris Austen0ba649e2015-10-13 12:28:13 -050054{
55 unsigned int i, j;
Chris Austen120f7322015-10-14 23:27:31 -050056
Chris Austen0ba649e2015-10-13 12:28:13 -050057 for(i = 0; i < len + ((len % HEXDUMP_COLS) ? (HEXDUMP_COLS - len % HEXDUMP_COLS) : 0); i++)
58 {
59 /* print offset */
60 if(i % HEXDUMP_COLS == 0)
61 {
Chris Austen99497312015-10-22 13:00:16 -050062 fprintf(s,"0x%06x: ", i);
Chris Austen0ba649e2015-10-13 12:28:13 -050063 }
Chris Austen120f7322015-10-14 23:27:31 -050064
Chris Austen0ba649e2015-10-13 12:28:13 -050065 /* print hex data */
66 if(i < len)
67 {
Chris Austen99497312015-10-22 13:00:16 -050068 fprintf(s,"%02x ", 0xFF & ((char*)mem)[i]);
Chris Austen0ba649e2015-10-13 12:28:13 -050069 }
70 else /* end of block, just aligning for ASCII dump */
71 {
Chris Austen99497312015-10-22 13:00:16 -050072 fprintf(s," ");
Chris Austen0ba649e2015-10-13 12:28:13 -050073 }
Chris Austen120f7322015-10-14 23:27:31 -050074
Chris Austen0ba649e2015-10-13 12:28:13 -050075 /* print ASCII dump */
76 if(i % HEXDUMP_COLS == (HEXDUMP_COLS - 1))
77 {
78 for(j = i - (HEXDUMP_COLS - 1); j <= i; j++)
79 {
80 if(j >= len) /* end of block, not really printing */
81 {
Chris Austen99497312015-10-22 13:00:16 -050082 fputc(' ', s);
Chris Austen0ba649e2015-10-13 12:28:13 -050083 }
84 else if(isprint(((char*)mem)[j])) /* printable char */
85 {
Chris Austen99497312015-10-22 13:00:16 -050086 fputc(0xFF & ((char*)mem)[j], s);
Chris Austen0ba649e2015-10-13 12:28:13 -050087 }
88 else /* other char */
89 {
Chris Austen99497312015-10-22 13:00:16 -050090 fputc('.',s);
Chris Austen0ba649e2015-10-13 12:28:13 -050091 }
92 }
Chris Austen99497312015-10-22 13:00:16 -050093 fputc('\n',s);
Chris Austen0ba649e2015-10-13 12:28:13 -050094 }
95 }
96}
97
98
vishwabmcba0bd5f2015-09-30 16:50:23 +053099// Method that gets called by shared libraries to get their command handlers registered
100void ipmi_register_callback(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
101 ipmi_context_t context, ipmid_callback_t handler)
102{
103 // Pack NetFn and Command in one.
104 auto netfn_and_cmd = std::make_pair(netfn, cmd);
105
106 // Pack Function handler and Data in another.
107 auto handler_and_context = std::make_pair(handler, context);
108
109 // Check if the registration has already been made..
110 auto iter = g_ipmid_router_map.find(netfn_and_cmd);
111 if(iter != g_ipmid_router_map.end())
112 {
113 fprintf(stderr,"ERROR : Duplicate registration for NetFn [0x%X], Cmd:[0x%X]\n",netfn, cmd);
114 }
115 else
116 {
117 // This is a fresh registration.. Add it to the map.
118 g_ipmid_router_map.emplace(netfn_and_cmd, handler_and_context);
119 }
120
121 return;
122}
123
124// Looks at the map and calls corresponding handler functions.
125ipmi_ret_t ipmi_netfn_router(ipmi_netfn_t netfn, ipmi_cmd_t cmd, ipmi_request_t request,
126 ipmi_response_t response, ipmi_data_len_t data_len)
127{
128 // return from the Command handlers.
129 ipmi_ret_t rc = IPMI_CC_INVALID;
130
131 // Walk the map that has the registered handlers and invoke the approprite
132 // handlers for matching commands.
133 auto iter = g_ipmid_router_map.find(std::make_pair(netfn, cmd));
134 if(iter == g_ipmid_router_map.end())
135 {
Chris Austen99497312015-10-22 13:00:16 -0500136 fprintf(stderr, "No registered handlers for NetFn:[0x%X], Cmd:[0x%X]"
vishwabmcba0bd5f2015-09-30 16:50:23 +0530137 " trying Wilcard implementation \n",netfn, cmd);
138
139 // Now that we did not find any specific [NetFn,Cmd], tuple, check for
140 // NetFn, WildCard command present.
141 iter = g_ipmid_router_map.find(std::make_pair(netfn, IPMI_CMD_WILDCARD));
142 if(iter == g_ipmid_router_map.end())
143 {
Chris Austen99497312015-10-22 13:00:16 -0500144 fprintf(stderr, "No Registered handlers for NetFn:[0x%X],Cmd:[0x%X]\n",netfn, IPMI_CMD_WILDCARD);
vishwabmcba0bd5f2015-09-30 16:50:23 +0530145
146 // Respond with a 0xC1
147 memcpy(response, &rc, IPMI_CC_LEN);
148 *data_len = IPMI_CC_LEN;
149 return rc;
150 }
151 }
152
153#ifdef __IPMI_DEBUG__
154 // We have either a perfect match -OR- a wild card atleast,
155 printf("Calling Net function:[0x%X], Command:[0x%X]\n", netfn, cmd);
156#endif
157
158 // Extract the map data onto appropriate containers
159 auto handler_and_context = iter->second;
160
161 // Creating a pointer type casted to char* to make sure we advance 1 byte
162 // when we advance pointer to next's address. advancing void * would not
163 // make sense.
164 char *respo = &((char *)response)[IPMI_CC_LEN];
165
166 // Response message from the plugin goes into a byte post the base response
167 rc = (handler_and_context.first) (netfn, cmd, request, respo,
168 data_len, handler_and_context.second);
Chris Austen120f7322015-10-14 23:27:31 -0500169
vishwabmcba0bd5f2015-09-30 16:50:23 +0530170 // Now copy the return code that we got from handler and pack it in first
171 // byte.
172 memcpy(response, &rc, IPMI_CC_LEN);
Chris Austen120f7322015-10-14 23:27:31 -0500173
vishwabmcba0bd5f2015-09-30 16:50:23 +0530174 // Data length is now actual data + completion code.
175 *data_len = *data_len + IPMI_CC_LEN;
176
177 return rc;
178}
179
vishwabmcba0bd5f2015-09-30 16:50:23 +0530180
vishwabmcba0bd5f2015-09-30 16:50:23 +0530181
vishwabmcba0bd5f2015-09-30 16:50:23 +0530182
Jeremy Kerr2564b1a2015-10-27 13:37:17 +0800183static 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 +0530184
Chris Austen0ba649e2015-10-13 12:28:13 -0500185 sd_bus_error error = SD_BUS_ERROR_NULL;
186 sd_bus_message *reply = NULL, *m=NULL;
Jeremy Kerre41081f2015-10-27 12:11:36 +0800187 const char *dest, *path;
Chris Austen0ba649e2015-10-13 12:28:13 -0500188 int r, pty;
vishwabmcba0bd5f2015-09-30 16:50:23 +0530189
Jeremy Kerre41081f2015-10-27 12:11:36 +0800190 dest = sd_bus_message_get_sender(req);
191 path = sd_bus_message_get_path(req);
vishwabmcba0bd5f2015-09-30 16:50:23 +0530192
Jeremy Kerre41081f2015-10-27 12:11:36 +0800193 r = sd_bus_message_new_method_call(bus,&m,dest,path,DBUS_INTF,"sendMessage");
Chris Austen0ba649e2015-10-13 12:28:13 -0500194 if (r < 0) {
195 fprintf(stderr, "Failed to add the method object: %s\n", strerror(-r));
196 return -1;
vishwabmcba0bd5f2015-09-30 16:50:23 +0530197 }
198
vishwabmcba0bd5f2015-09-30 16:50:23 +0530199
Chris Austenabfb5e82015-10-13 12:29:24 -0500200 // Responses in IPMI require a bit set. So there ya go...
Jeremy Kerr2564b1a2015-10-27 13:37:17 +0800201 netfn |= 0x01;
vishwabmcba0bd5f2015-09-30 16:50:23 +0530202
Chris Austen0ba649e2015-10-13 12:28:13 -0500203
204 // Add the bytes needed for the methods to be called
Jeremy Kerr2564b1a2015-10-27 13:37:17 +0800205 r = sd_bus_message_append(m, "yyyyy", seq, netfn, lun, cmd, cc);
Chris Austen0ba649e2015-10-13 12:28:13 -0500206 if (r < 0) {
207 fprintf(stderr, "Failed add the netfn and others : %s\n", strerror(-r));
Chris Austen169395e2015-12-02 20:56:15 -0600208 goto final;
Chris Austen0ba649e2015-10-13 12:28:13 -0500209 }
Chris Austen120f7322015-10-14 23:27:31 -0500210
Chris Austen0ba649e2015-10-13 12:28:13 -0500211 r = sd_bus_message_append_array(m, 'y', buf, len);
212 if (r < 0) {
213 fprintf(stderr, "Failed to add the string of response bytes: %s\n", strerror(-r));
Chris Austen169395e2015-12-02 20:56:15 -0600214 goto final;
Chris Austen0ba649e2015-10-13 12:28:13 -0500215 }
216
217
218
219 // Call the IPMI responder on the bus so the message can be sent to the CEC
220 r = sd_bus_call(bus, m, 0, &error, &reply);
221 if (r < 0) {
Chris Austen169395e2015-12-02 20:56:15 -0600222 fprintf(stderr, "Failed to call the method: %s\n", strerror(-r));
Chris Austen6bd23962015-12-07 21:31:48 -0600223 fprintf(stderr, "Dest: %s, Path: %s\n", dest, path);
Chris Austen169395e2015-12-02 20:56:15 -0600224 goto final;
Chris Austen0ba649e2015-10-13 12:28:13 -0500225 }
226
227 r = sd_bus_message_read(reply, "x", &pty);
Chris Austen0ba649e2015-10-13 12:28:13 -0500228 if (r < 0) {
229 fprintf(stderr, "Failed to get a rc from the method: %s\n", strerror(-r));
Chris Austen0ba649e2015-10-13 12:28:13 -0500230 }
231
Chris Austen169395e2015-12-02 20:56:15 -0600232final:
Chris Austen0ba649e2015-10-13 12:28:13 -0500233 sd_bus_error_free(&error);
vishwa1eaea4f2016-02-26 11:57:40 -0600234 m = sd_bus_message_unref(m);
235 reply = sd_bus_message_unref(reply);
Chris Austen0ba649e2015-10-13 12:28:13 -0500236
Chris Austen0ba649e2015-10-13 12:28:13 -0500237 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
Chris Austen0ba649e2015-10-13 12:28:13 -0500238}
239
240static int handle_ipmi_command(sd_bus_message *m, void *user_data, sd_bus_error
241 *ret_error) {
242 int r = 0;
Jeremy Kerr2564b1a2015-10-27 13:37:17 +0800243 unsigned char sequence, netfn, lun, cmd;
Chris Austen0ba649e2015-10-13 12:28:13 -0500244 const void *request;
245 size_t sz;
246 size_t resplen =MAX_IPMI_BUFFER;
247 unsigned char response[MAX_IPMI_BUFFER];
248
Chris Austen0ba649e2015-10-13 12:28:13 -0500249 memset(response, 0, MAX_IPMI_BUFFER);
250
Jeremy Kerr2564b1a2015-10-27 13:37:17 +0800251 r = sd_bus_message_read(m, "yyyy", &sequence, &netfn, &lun, &cmd);
Chris Austen0ba649e2015-10-13 12:28:13 -0500252 if (r < 0) {
253 fprintf(stderr, "Failed to parse signal message: %s\n", strerror(-r));
254 return -1;
255 }
256
257 r = sd_bus_message_read_array(m, 'y', &request, &sz );
258 if (r < 0) {
259 fprintf(stderr, "Failed to parse signal message: %s\n", strerror(-r));
260 return -1;
261 }
262
Chris Austen99497312015-10-22 13:00:16 -0500263 fprintf(ipmiio, "IPMI Incoming: Seq 0x%02x, NetFn 0x%02x, CMD: 0x%02x \n", sequence, netfn, cmd);
264 hexdump(ipmiio, (void*)request, sz);
Chris Austen0ba649e2015-10-13 12:28:13 -0500265
Chris Austen120f7322015-10-14 23:27:31 -0500266 // Allow the length field to be used for both input and output of the
Chris Austen0ba649e2015-10-13 12:28:13 -0500267 // ipmi call
268 resplen = sz;
269
Chris Austen120f7322015-10-14 23:27:31 -0500270 // Now that we have parsed the entire byte array from the caller
vishwabmcba0bd5f2015-09-30 16:50:23 +0530271 // we can call the ipmi router to do the work...
Chris Austen0ba649e2015-10-13 12:28:13 -0500272 r = ipmi_netfn_router(netfn, cmd, (void *)request, (void *)response, &resplen);
273 if(r != 0)
vishwabmcba0bd5f2015-09-30 16:50:23 +0530274 {
Chris Austen0ba649e2015-10-13 12:28:13 -0500275 fprintf(stderr,"ERROR:[0x%X] handling NetFn:[0x%X], Cmd:[0x%X]\n",r, netfn, cmd);
Nan Li80be4b92016-05-23 19:30:49 +0800276
tomjose7ec0add2016-06-27 07:59:28 -0500277 if(r < 0) {
Nan Li80be4b92016-05-23 19:30:49 +0800278 response[0] = IPMI_CC_UNSPECIFIED_ERROR;
279 }
vishwabmcba0bd5f2015-09-30 16:50:23 +0530280 }
281
Chris Austen99497312015-10-22 13:00:16 -0500282 fprintf(ipmiio, "IPMI Response:\n");
283 hexdump(ipmiio, (void*)response, resplen);
vishwabmcba0bd5f2015-09-30 16:50:23 +0530284
Chris Austen0ba649e2015-10-13 12:28:13 -0500285 // Send the response buffer from the ipmi command
Jeremy Kerr2564b1a2015-10-27 13:37:17 +0800286 r = send_ipmi_message(m, sequence, netfn, lun, cmd, response[0],
287 ((unsigned char *)response) + 1, resplen - 1);
Chris Austen0ba649e2015-10-13 12:28:13 -0500288 if (r < 0) {
289 fprintf(stderr, "Failed to send the response message\n");
290 return -1;
vishwabmcba0bd5f2015-09-30 16:50:23 +0530291 }
292
vishwabmcba0bd5f2015-09-30 16:50:23 +0530293
Chris Austen0ba649e2015-10-13 12:28:13 -0500294 return 0;
vishwabmcba0bd5f2015-09-30 16:50:23 +0530295}
296
Chris Austen0ba649e2015-10-13 12:28:13 -0500297
vishwabmcba0bd5f2015-09-30 16:50:23 +0530298//----------------------------------------------------------------------
299// handler_select
300// Select all the files ending with with .so. in the given diretcory
301// @d: dirent structure containing the file name
302//----------------------------------------------------------------------
303int handler_select(const struct dirent *entry)
304{
305 // To hold ".so" from entry->d_name;
306 char dname_copy[4] = {0};
307
308 // We want to avoid checking for everything and isolate to the ones having
Adriana Kobylak87e080b2016-07-10 13:16:53 -0500309 // .so.* or .so in them.
310 // Check for versioned libraries .so.*
311 if(strstr(entry->d_name, IPMI_PLUGIN_SONAME_EXTN))
312 {
313 return 1;
314 }
315 // Check for non versioned libraries .so
316 else if(strstr(entry->d_name, IPMI_PLUGIN_EXTN))
vishwabmcba0bd5f2015-09-30 16:50:23 +0530317 {
318 // It is possible that .so could be anywhere in the string but unlikely
Chris Austen120f7322015-10-14 23:27:31 -0500319 // But being careful here. Get the base address of the string, move
vishwabmcba0bd5f2015-09-30 16:50:23 +0530320 // until end and come back 3 steps and that gets what we need.
321 strcpy(dname_copy, (entry->d_name + strlen(entry->d_name)-strlen(IPMI_PLUGIN_EXTN)));
322 if(strcmp(dname_copy, IPMI_PLUGIN_EXTN) == 0)
323 {
324 return 1;
325 }
326 }
327 return 0;
328}
329
330// 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 -0500331// register a callback handler
vishwabmcba0bd5f2015-09-30 16:50:23 +0530332void ipmi_register_callback_handlers(const char* ipmi_lib_path)
333{
334 // For walking the ipmi_lib_path
335 struct dirent **handler_list;
336 int num_handlers = 0;
337
338 // This is used to check and abort if someone tries to register a bad one.
339 void *lib_handler = NULL;
340
341 if(ipmi_lib_path == NULL)
342 {
343 fprintf(stderr,"ERROR; No handlers to be registered for ipmi.. Aborting\n");
344 assert(0);
345 }
346 else
347 {
348 // 1: Open ipmi_lib_path. Its usually "/usr/lib/phosphor-host-ipmid"
349 // 2: Scan the directory for the files that end with .so
Chris Austen120f7322015-10-14 23:27:31 -0500350 // 3: For each one of them, just do a 'dlopen' so that they register
vishwabmcba0bd5f2015-09-30 16:50:23 +0530351 // the handlers for callback routines.
352
353 std::string handler_fqdn = ipmi_lib_path;
Chris Austen120f7322015-10-14 23:27:31 -0500354
vishwabmcba0bd5f2015-09-30 16:50:23 +0530355 // Append a "/" since we need to add the name of the .so. If there is
356 // already a .so, adding one more is not any harm.
357 handler_fqdn += "/";
358
359 num_handlers = scandir(ipmi_lib_path, &handler_list, handler_select, alphasort);
Nan Li36c0cb62016-03-31 11:16:08 +0800360 if (num_handlers < 0)
361 return;
Jeremy Kerr5e8f85e2015-10-27 13:43:54 +0800362
vishwabmcba0bd5f2015-09-30 16:50:23 +0530363 while(num_handlers--)
364 {
Chris Austen54030262015-10-13 12:30:46 -0500365 handler_fqdn = ipmi_lib_path;
vishwabmcba0bd5f2015-09-30 16:50:23 +0530366 handler_fqdn += handler_list[num_handlers]->d_name;
Chris Austen54030262015-10-13 12:30:46 -0500367 printf("Registering handler:[%s]\n",handler_fqdn.c_str());
368
vishwabmcba0bd5f2015-09-30 16:50:23 +0530369 lib_handler = dlopen(handler_fqdn.c_str(), RTLD_NOW);
Nan Li36c0cb62016-03-31 11:16:08 +0800370
vishwabmcba0bd5f2015-09-30 16:50:23 +0530371 if(lib_handler == NULL)
372 {
Chris Austen120f7322015-10-14 23:27:31 -0500373 fprintf(stderr,"ERROR opening [%s]: %s\n",
374 handler_fqdn.c_str(), dlerror());
vishwabmcba0bd5f2015-09-30 16:50:23 +0530375 }
376 // Wipe the memory allocated for this particular entry.
377 free(handler_list[num_handlers]);
378 }
Nan Li36c0cb62016-03-31 11:16:08 +0800379
vishwabmcba0bd5f2015-09-30 16:50:23 +0530380 // Done with all registration.
381 free(handler_list);
382 }
383
384 // TODO : What to be done on the memory that is given by dlopen ?.
385 return;
386}
387
Chris Austen30195fa2015-11-13 14:39:19 -0600388sd_bus *ipmid_get_sd_bus_connection(void) {
389 return bus;
390}
391
vishwab9f559a2016-01-13 01:53:08 -0600392sd_bus_slot *ipmid_get_sd_bus_slot(void) {
393 return ipmid_slot;
394}
395
vishwabmcba0bd5f2015-09-30 16:50:23 +0530396int main(int argc, char *argv[])
397{
Chris Austen0ba649e2015-10-13 12:28:13 -0500398 int r;
Chris Austen99497312015-10-22 13:00:16 -0500399 unsigned long tvalue;
400 int c;
401
402
403
404 // This file and subsequient switch is for turning on levels
405 // of trace
406 ipmicmddetails = ipmiio = ipmidbus = fopen("/dev/null", "w");
407
408 while ((c = getopt (argc, argv, "h:d:")) != -1)
409 switch (c) {
410 case 'd':
411 tvalue = strtoul(optarg, NULL, 16);
412 if (1&tvalue) {
413 ipmiio = stdout;
414 }
415 if (2&tvalue) {
416 ipmidbus = stdout;
417 }
418 if (4&tvalue) {
419 ipmicmddetails = stdout;
420 }
421 break;
422 case 'h':
423 case '?':
424 print_usage();
425 return 1;
426 }
Chris Austen0ba649e2015-10-13 12:28:13 -0500427
428
Chris Austen0ba649e2015-10-13 12:28:13 -0500429 /* Connect to system bus */
430 r = sd_bus_open_system(&bus);
431 if (r < 0) {
432 fprintf(stderr, "Failed to connect to system bus: %s\n",
433 strerror(-r));
434 goto finish;
435 }
vishwabmcba0bd5f2015-09-30 16:50:23 +0530436
Chris Austen30195fa2015-11-13 14:39:19 -0600437 // Register all the handlers that provider implementation to IPMI commands.
438 ipmi_register_callback_handlers(HOST_IPMI_LIB_PATH);
439
vishwa36993272015-11-20 12:43:49 -0600440 // Watch for BT messages
vishwab9f559a2016-01-13 01:53:08 -0600441 r = sd_bus_add_match(bus, &ipmid_slot, FILTER, handle_ipmi_command, NULL);
Chris Austen0ba649e2015-10-13 12:28:13 -0500442 if (r < 0) {
443 fprintf(stderr, "Failed: sd_bus_add_match: %s : %s\n", strerror(-r), FILTER);
444 goto finish;
445 }
vishwabmcba0bd5f2015-09-30 16:50:23 +0530446
vishwabmcba0bd5f2015-09-30 16:50:23 +0530447
Chris Austen0ba649e2015-10-13 12:28:13 -0500448 for (;;) {
449 /* Process requests */
Chris Austen0ba649e2015-10-13 12:28:13 -0500450 r = sd_bus_process(bus, NULL);
451 if (r < 0) {
452 fprintf(stderr, "Failed to process bus: %s\n", strerror(-r));
453 goto finish;
454 }
455 if (r > 0) {
456 continue;
457 }
458
459 r = sd_bus_wait(bus, (uint64_t) - 1);
460 if (r < 0) {
461 fprintf(stderr, "Failed to wait on bus: %s\n", strerror(-r));
462 goto finish;
463 }
464 }
465
466finish:
vishwab9f559a2016-01-13 01:53:08 -0600467 sd_bus_slot_unref(ipmid_slot);
Chris Austen0ba649e2015-10-13 12:28:13 -0500468 sd_bus_unref(bus);
469 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
470
vishwabmcba0bd5f2015-09-30 16:50:23 +0530471}
Chris Austenb071c702015-10-15 00:00:09 -0500472
Chris Austen0012e9b2015-10-22 01:37:46 -0500473// Use a lookup table to find the interface name of a specific sensor
474// This will be used until an alternative is found. this is the first
475// step for mapping IPMI
476int find_interface_property_fru_type(dbus_interface_t *interface, const char *property_name, char *property_value) {
Chris Austenb071c702015-10-15 00:00:09 -0500477
Joel Stanleyf19539e2015-11-25 17:24:05 +1030478 char *str1;
Chris Austen0012e9b2015-10-22 01:37:46 -0500479 sd_bus_error error = SD_BUS_ERROR_NULL;
480 sd_bus_message *reply = NULL, *m=NULL;
Chris Austenb071c702015-10-15 00:00:09 -0500481
482
Chris Austen0012e9b2015-10-22 01:37:46 -0500483 int r;
484
Chris Austen0012e9b2015-10-22 01:37:46 -0500485 r = sd_bus_message_new_method_call(bus,&m,interface->bus,interface->path,"org.freedesktop.DBus.Properties","Get");
486 if (r < 0) {
487 fprintf(stderr, "Failed to create a method call: %s", strerror(-r));
488 fprintf(stderr,"Bus: %s Path: %s Interface: %s \n",
489 interface->bus, interface->path, interface->interface);
vishwa1eaea4f2016-02-26 11:57:40 -0600490 goto final;
Chris Austen0012e9b2015-10-22 01:37:46 -0500491 }
492
493 r = sd_bus_message_append(m, "ss", "org.openbmc.InventoryItem", property_name);
494 if (r < 0) {
495 fprintf(stderr, "Failed to create a input parameter: %s", strerror(-r));
496 fprintf(stderr,"Bus: %s Path: %s Interface: %s \n",
497 interface->bus, interface->path, interface->interface);
vishwa1eaea4f2016-02-26 11:57:40 -0600498 goto final;
Chris Austen0012e9b2015-10-22 01:37:46 -0500499 }
500
501 r = sd_bus_call(bus, m, 0, &error, &reply);
502 if (r < 0) {
503 fprintf(stderr, "Failed to call the method: %s", strerror(-r));
504 goto final;
505 }
506
507 r = sd_bus_message_read(reply, "v", "s", &str1) ;
508 if (r < 0) {
509 fprintf(stderr, "Failed to get a response: %s", strerror(-r));
510 goto final;
511 }
512
513 strcpy(property_value, str1);
514
515final:
516
517 sd_bus_error_free(&error);
vishwa1eaea4f2016-02-26 11:57:40 -0600518 m = sd_bus_message_unref(m);
519 reply = sd_bus_message_unref(reply);
Chris Austen0012e9b2015-10-22 01:37:46 -0500520
521 return r;
522}
Chris Austenb071c702015-10-15 00:00:09 -0500523
Chris Austen41a4b312015-10-25 03:45:42 -0500524
Chris Austenb071c702015-10-15 00:00:09 -0500525// Use a lookup table to find the interface name of a specific sensor
526// This will be used until an alternative is found. this is the first
527// step for mapping IPMI
528int find_openbmc_path(const char *type, const uint8_t num, dbus_interface_t *interface) {
Brad Bishop35518682016-07-22 08:35:41 -0400529 char *busname = NULL;
530 const char *iface = "org.openbmc.managers.System";
Chris Austenb071c702015-10-15 00:00:09 -0500531 const char *objname = "/org/openbmc/managers/System";
Brad Bishop35518682016-07-22 08:35:41 -0400532 char *str1 = NULL, *str2, *str3;
Chris Austenb071c702015-10-15 00:00:09 -0500533 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;
Brad Bishop35518682016-07-22 08:35:41 -0400538 r = mapper_get_service(bus, objname, &busname);
539 if (r < 0) {
540 fprintf(stderr, "Failed to get system manager busname: %s\n", strerror(-r));
541 goto final;
542 }
Chris Austenb071c702015-10-15 00:00:09 -0500543
Brad Bishop35518682016-07-22 08:35:41 -0400544 r = sd_bus_call_method(bus,busname,objname,iface, "getObjectFromByteId",
vishwa1eaea4f2016-02-26 11:57:40 -0600545 &error, &reply, "sy", type, num);
Chris Austenb071c702015-10-15 00:00:09 -0500546 if (r < 0) {
547 fprintf(stderr, "Failed to create a method call: %s", strerror(-r));
Chris Austenb071c702015-10-15 00:00:09 -0500548 goto final;
549 }
550
Brad Bishop35518682016-07-22 08:35:41 -0400551 r = sd_bus_message_read(reply, "(ss)", &str2, &str3);
Chris Austenb071c702015-10-15 00:00:09 -0500552 if (r < 0) {
553 fprintf(stderr, "Failed to get a response: %s", strerror(-r));
554 goto final;
555 }
556
Brad Bishop35518682016-07-22 08:35:41 -0400557 r = mapper_get_service(bus, str2, &str1);
558 if (r < 0) {
559 fprintf(stderr, "Failed to get item busname: %s\n", strerror(-r));
560 goto final;
561 }
562
Chris Austenb071c702015-10-15 00:00:09 -0500563 strncpy(interface->bus, str1, MAX_DBUS_PATH);
564 strncpy(interface->path, str2, MAX_DBUS_PATH);
565 strncpy(interface->interface, str3, MAX_DBUS_PATH);
566
567 interface->sensornumber = num;
568
Chris Austenb071c702015-10-15 00:00:09 -0500569final:
570
571 sd_bus_error_free(&error);
vishwa1eaea4f2016-02-26 11:57:40 -0600572 reply = sd_bus_message_unref(reply);
Brad Bishop35518682016-07-22 08:35:41 -0400573 free(busname);
574 free(str1);
Chris Austenb071c702015-10-15 00:00:09 -0500575
576 return r;
577}
578
579
580/////////////////////////////////////////////////////////////////////
581//
582// Routines used by ipmi commands wanting to interact on the dbus
583//
584/////////////////////////////////////////////////////////////////////
Chris Austen10ccc0f2015-12-10 18:27:04 -0600585int set_sensor_dbus_state_s(uint8_t number, const char *method, const char *value) {
Chris Austen0130d6e2015-10-15 22:32:36 -0500586
587
588 dbus_interface_t a;
589 int r;
590 sd_bus_error error = SD_BUS_ERROR_NULL;
Joel Stanleyf19539e2015-11-25 17:24:05 +1030591 sd_bus_message *m=NULL;
Chris Austen0130d6e2015-10-15 22:32:36 -0500592
Chris Austen99497312015-10-22 13:00:16 -0500593 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 -0500594 number, method, value);
595
596 r = find_openbmc_path("SENSOR", number, &a);
597
Nan Li36deb762016-05-12 10:23:41 +0800598 if (r < 0) {
599 fprintf(stderr, "Failed to find Sensor 0x%02x\n", number);
600 return 0;
601 }
602
Chris Austen0130d6e2015-10-15 22:32:36 -0500603 r = sd_bus_message_new_method_call(bus,&m,a.bus,a.path,a.interface,method);
604 if (r < 0) {
605 fprintf(stderr, "Failed to create a method call: %s", strerror(-r));
vishwa1eaea4f2016-02-26 11:57:40 -0600606 goto final;
Chris Austen0130d6e2015-10-15 22:32:36 -0500607 }
608
609 r = sd_bus_message_append(m, "v", "s", value);
610 if (r < 0) {
611 fprintf(stderr, "Failed to create a input parameter: %s", strerror(-r));
vishwa1eaea4f2016-02-26 11:57:40 -0600612 goto final;
Chris Austen0130d6e2015-10-15 22:32:36 -0500613 }
614
615
Chris Austen0130d6e2015-10-15 22:32:36 -0500616 r = sd_bus_call(bus, m, 0, &error, NULL);
617 if (r < 0) {
Chris Austen10ccc0f2015-12-10 18:27:04 -0600618 fprintf(stderr, "Failed to call the method: %s", strerror(-r));
Chris Austen0130d6e2015-10-15 22:32:36 -0500619 }
620
vishwa1eaea4f2016-02-26 11:57:40 -0600621final:
Chris Austen0130d6e2015-10-15 22:32:36 -0500622 sd_bus_error_free(&error);
vishwa1eaea4f2016-02-26 11:57:40 -0600623 m = sd_bus_message_unref(m);
Chris Austen0130d6e2015-10-15 22:32:36 -0500624
625 return 0;
626}
Chris Austen10ccc0f2015-12-10 18:27:04 -0600627int set_sensor_dbus_state_y(uint8_t number, const char *method, const uint8_t value) {
628
629
630 dbus_interface_t a;
631 int r;
632 sd_bus_error error = SD_BUS_ERROR_NULL;
633 sd_bus_message *m=NULL;
634
635 fprintf(ipmidbus, "Attempting to set a dbus Variant Sensor 0x%02x via %s with a value of 0x%02x\n",
636 number, method, value);
637
638 r = find_openbmc_path("SENSOR", number, &a);
639
Nan Li36deb762016-05-12 10:23:41 +0800640 if (r < 0) {
641 fprintf(stderr, "Failed to find Sensor 0x%02x\n", number);
642 return 0;
643 }
644
Chris Austen10ccc0f2015-12-10 18:27:04 -0600645 r = sd_bus_message_new_method_call(bus,&m,a.bus,a.path,a.interface,method);
646 if (r < 0) {
647 fprintf(stderr, "Failed to create a method call: %s", strerror(-r));
vishwa1eaea4f2016-02-26 11:57:40 -0600648 goto final;
Chris Austen10ccc0f2015-12-10 18:27:04 -0600649 }
650
Adriana Kobylak93125982016-03-01 12:48:10 -0600651 r = sd_bus_message_append(m, "v", "i", value);
Chris Austen10ccc0f2015-12-10 18:27:04 -0600652 if (r < 0) {
653 fprintf(stderr, "Failed to create a input parameter: %s", strerror(-r));
vishwa1eaea4f2016-02-26 11:57:40 -0600654 goto final;
Chris Austen10ccc0f2015-12-10 18:27:04 -0600655 }
656
657
658 r = sd_bus_call(bus, m, 0, &error, NULL);
659 if (r < 0) {
660 fprintf(stderr, "12 Failed to call the method: %s", strerror(-r));
661 }
662
vishwa1eaea4f2016-02-26 11:57:40 -0600663final:
Chris Austen10ccc0f2015-12-10 18:27:04 -0600664 sd_bus_error_free(&error);
vishwa1eaea4f2016-02-26 11:57:40 -0600665 m = sd_bus_message_unref(m);
Chris Austen10ccc0f2015-12-10 18:27:04 -0600666
667 return 0;
vishwa1eaea4f2016-02-26 11:57:40 -0600668}