blob: 6071cb3bbd2f6263e56f85ebb6aee12860ad8750 [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
16
Chris Austen6bd23962015-12-07 21:31:48 -060017
Chris Austen0ba649e2015-10-13 12:28:13 -050018sd_bus *bus = 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
30
31
Jeremy Kerre41081f2015-10-27 12:11:36 +080032const char * DBUS_INTF = "org.openbmc.HostIpmi";
vishwabmcba0bd5f2015-09-30 16:50:23 +053033
Jeremy Kerre41081f2015-10-27 12:11:36 +080034const char * FILTER = "type='signal',interface='org.openbmc.HostIpmi',member='ReceivedMessage'";
Chris Austen0ba649e2015-10-13 12:28:13 -050035
36
vishwabmcba0bd5f2015-09-30 16:50:23 +053037typedef std::pair<ipmi_netfn_t, ipmi_cmd_t> ipmi_fn_cmd_t;
38typedef std::pair<ipmid_callback_t, ipmi_context_t> ipmi_fn_context_t;
39
40// Global data structure that contains the IPMI command handler's registrations.
41std::map<ipmi_fn_cmd_t, ipmi_fn_context_t> g_ipmid_router_map;
42
Chris Austen0ba649e2015-10-13 12:28:13 -050043
Chris Austen0ba649e2015-10-13 12:28:13 -050044#ifndef HEXDUMP_COLS
45#define HEXDUMP_COLS 16
46#endif
47
Chris Austen99497312015-10-22 13:00:16 -050048void hexdump(FILE *s, void *mem, size_t len)
Chris Austen0ba649e2015-10-13 12:28:13 -050049{
50 unsigned int i, j;
Chris Austen120f7322015-10-14 23:27:31 -050051
Chris Austen0ba649e2015-10-13 12:28:13 -050052 for(i = 0; i < len + ((len % HEXDUMP_COLS) ? (HEXDUMP_COLS - len % HEXDUMP_COLS) : 0); i++)
53 {
54 /* print offset */
55 if(i % HEXDUMP_COLS == 0)
56 {
Chris Austen99497312015-10-22 13:00:16 -050057 fprintf(s,"0x%06x: ", i);
Chris Austen0ba649e2015-10-13 12:28:13 -050058 }
Chris Austen120f7322015-10-14 23:27:31 -050059
Chris Austen0ba649e2015-10-13 12:28:13 -050060 /* print hex data */
61 if(i < len)
62 {
Chris Austen99497312015-10-22 13:00:16 -050063 fprintf(s,"%02x ", 0xFF & ((char*)mem)[i]);
Chris Austen0ba649e2015-10-13 12:28:13 -050064 }
65 else /* end of block, just aligning for ASCII dump */
66 {
Chris Austen99497312015-10-22 13:00:16 -050067 fprintf(s," ");
Chris Austen0ba649e2015-10-13 12:28:13 -050068 }
Chris Austen120f7322015-10-14 23:27:31 -050069
Chris Austen0ba649e2015-10-13 12:28:13 -050070 /* print ASCII dump */
71 if(i % HEXDUMP_COLS == (HEXDUMP_COLS - 1))
72 {
73 for(j = i - (HEXDUMP_COLS - 1); j <= i; j++)
74 {
75 if(j >= len) /* end of block, not really printing */
76 {
Chris Austen99497312015-10-22 13:00:16 -050077 fputc(' ', s);
Chris Austen0ba649e2015-10-13 12:28:13 -050078 }
79 else if(isprint(((char*)mem)[j])) /* printable char */
80 {
Chris Austen99497312015-10-22 13:00:16 -050081 fputc(0xFF & ((char*)mem)[j], s);
Chris Austen0ba649e2015-10-13 12:28:13 -050082 }
83 else /* other char */
84 {
Chris Austen99497312015-10-22 13:00:16 -050085 fputc('.',s);
Chris Austen0ba649e2015-10-13 12:28:13 -050086 }
87 }
Chris Austen99497312015-10-22 13:00:16 -050088 fputc('\n',s);
Chris Austen0ba649e2015-10-13 12:28:13 -050089 }
90 }
91}
92
93
vishwabmcba0bd5f2015-09-30 16:50:23 +053094// Method that gets called by shared libraries to get their command handlers registered
95void ipmi_register_callback(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
96 ipmi_context_t context, ipmid_callback_t handler)
97{
98 // Pack NetFn and Command in one.
99 auto netfn_and_cmd = std::make_pair(netfn, cmd);
100
101 // Pack Function handler and Data in another.
102 auto handler_and_context = std::make_pair(handler, context);
103
104 // Check if the registration has already been made..
105 auto iter = g_ipmid_router_map.find(netfn_and_cmd);
106 if(iter != g_ipmid_router_map.end())
107 {
108 fprintf(stderr,"ERROR : Duplicate registration for NetFn [0x%X], Cmd:[0x%X]\n",netfn, cmd);
109 }
110 else
111 {
112 // This is a fresh registration.. Add it to the map.
113 g_ipmid_router_map.emplace(netfn_and_cmd, handler_and_context);
114 }
115
116 return;
117}
118
119// Looks at the map and calls corresponding handler functions.
120ipmi_ret_t ipmi_netfn_router(ipmi_netfn_t netfn, ipmi_cmd_t cmd, ipmi_request_t request,
121 ipmi_response_t response, ipmi_data_len_t data_len)
122{
123 // return from the Command handlers.
124 ipmi_ret_t rc = IPMI_CC_INVALID;
125
126 // Walk the map that has the registered handlers and invoke the approprite
127 // handlers for matching commands.
128 auto iter = g_ipmid_router_map.find(std::make_pair(netfn, cmd));
129 if(iter == g_ipmid_router_map.end())
130 {
Chris Austen99497312015-10-22 13:00:16 -0500131 fprintf(stderr, "No registered handlers for NetFn:[0x%X], Cmd:[0x%X]"
vishwabmcba0bd5f2015-09-30 16:50:23 +0530132 " trying Wilcard implementation \n",netfn, cmd);
133
134 // Now that we did not find any specific [NetFn,Cmd], tuple, check for
135 // NetFn, WildCard command present.
136 iter = g_ipmid_router_map.find(std::make_pair(netfn, IPMI_CMD_WILDCARD));
137 if(iter == g_ipmid_router_map.end())
138 {
Chris Austen99497312015-10-22 13:00:16 -0500139 fprintf(stderr, "No Registered handlers for NetFn:[0x%X],Cmd:[0x%X]\n",netfn, IPMI_CMD_WILDCARD);
vishwabmcba0bd5f2015-09-30 16:50:23 +0530140
141 // Respond with a 0xC1
142 memcpy(response, &rc, IPMI_CC_LEN);
143 *data_len = IPMI_CC_LEN;
144 return rc;
145 }
146 }
147
148#ifdef __IPMI_DEBUG__
149 // We have either a perfect match -OR- a wild card atleast,
150 printf("Calling Net function:[0x%X], Command:[0x%X]\n", netfn, cmd);
151#endif
152
153 // Extract the map data onto appropriate containers
154 auto handler_and_context = iter->second;
155
156 // Creating a pointer type casted to char* to make sure we advance 1 byte
157 // when we advance pointer to next's address. advancing void * would not
158 // make sense.
159 char *respo = &((char *)response)[IPMI_CC_LEN];
160
161 // Response message from the plugin goes into a byte post the base response
162 rc = (handler_and_context.first) (netfn, cmd, request, respo,
163 data_len, handler_and_context.second);
Chris Austen120f7322015-10-14 23:27:31 -0500164
vishwabmcba0bd5f2015-09-30 16:50:23 +0530165 // Now copy the return code that we got from handler and pack it in first
166 // byte.
167 memcpy(response, &rc, IPMI_CC_LEN);
Chris Austen120f7322015-10-14 23:27:31 -0500168
vishwabmcba0bd5f2015-09-30 16:50:23 +0530169 // Data length is now actual data + completion code.
170 *data_len = *data_len + IPMI_CC_LEN;
171
172 return rc;
173}
174
vishwabmcba0bd5f2015-09-30 16:50:23 +0530175
vishwabmcba0bd5f2015-09-30 16:50:23 +0530176
vishwabmcba0bd5f2015-09-30 16:50:23 +0530177
Jeremy Kerr2564b1a2015-10-27 13:37:17 +0800178static 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 +0530179
Chris Austen0ba649e2015-10-13 12:28:13 -0500180 sd_bus_error error = SD_BUS_ERROR_NULL;
181 sd_bus_message *reply = NULL, *m=NULL;
Jeremy Kerre41081f2015-10-27 12:11:36 +0800182 const char *dest, *path;
Chris Austen0ba649e2015-10-13 12:28:13 -0500183 int r, pty;
vishwabmcba0bd5f2015-09-30 16:50:23 +0530184
Jeremy Kerre41081f2015-10-27 12:11:36 +0800185 dest = sd_bus_message_get_sender(req);
186 path = sd_bus_message_get_path(req);
vishwabmcba0bd5f2015-09-30 16:50:23 +0530187
Jeremy Kerre41081f2015-10-27 12:11:36 +0800188 r = sd_bus_message_new_method_call(bus,&m,dest,path,DBUS_INTF,"sendMessage");
Chris Austen0ba649e2015-10-13 12:28:13 -0500189 if (r < 0) {
190 fprintf(stderr, "Failed to add the method object: %s\n", strerror(-r));
191 return -1;
vishwabmcba0bd5f2015-09-30 16:50:23 +0530192 }
193
vishwabmcba0bd5f2015-09-30 16:50:23 +0530194
Chris Austenabfb5e82015-10-13 12:29:24 -0500195 // Responses in IPMI require a bit set. So there ya go...
Jeremy Kerr2564b1a2015-10-27 13:37:17 +0800196 netfn |= 0x01;
vishwabmcba0bd5f2015-09-30 16:50:23 +0530197
Chris Austen0ba649e2015-10-13 12:28:13 -0500198
199 // Add the bytes needed for the methods to be called
Jeremy Kerr2564b1a2015-10-27 13:37:17 +0800200 r = sd_bus_message_append(m, "yyyyy", seq, netfn, lun, cmd, cc);
Chris Austen0ba649e2015-10-13 12:28:13 -0500201 if (r < 0) {
202 fprintf(stderr, "Failed add the netfn and others : %s\n", strerror(-r));
Chris Austen169395e2015-12-02 20:56:15 -0600203 goto final;
Chris Austen0ba649e2015-10-13 12:28:13 -0500204 }
Chris Austen120f7322015-10-14 23:27:31 -0500205
Chris Austen0ba649e2015-10-13 12:28:13 -0500206 r = sd_bus_message_append_array(m, 'y', buf, len);
207 if (r < 0) {
208 fprintf(stderr, "Failed to add the string of response bytes: %s\n", strerror(-r));
Chris Austen169395e2015-12-02 20:56:15 -0600209 goto final;
Chris Austen0ba649e2015-10-13 12:28:13 -0500210 }
211
212
213
214 // Call the IPMI responder on the bus so the message can be sent to the CEC
215 r = sd_bus_call(bus, m, 0, &error, &reply);
216 if (r < 0) {
Chris Austen169395e2015-12-02 20:56:15 -0600217 fprintf(stderr, "Failed to call the method: %s\n", strerror(-r));
Chris Austen6bd23962015-12-07 21:31:48 -0600218 fprintf(stderr, "Dest: %s, Path: %s\n", dest, path);
Chris Austen169395e2015-12-02 20:56:15 -0600219 goto final;
Chris Austen0ba649e2015-10-13 12:28:13 -0500220 }
221
222 r = sd_bus_message_read(reply, "x", &pty);
Chris Austen0ba649e2015-10-13 12:28:13 -0500223 if (r < 0) {
224 fprintf(stderr, "Failed to get a rc from the method: %s\n", strerror(-r));
Chris Austen0ba649e2015-10-13 12:28:13 -0500225 }
226
Chris Austen169395e2015-12-02 20:56:15 -0600227final:
Chris Austen0ba649e2015-10-13 12:28:13 -0500228 sd_bus_error_free(&error);
229 sd_bus_message_unref(m);
Chris Austen169395e2015-12-02 20:56:15 -0600230 sd_bus_message_unref(reply);
Chris Austen0ba649e2015-10-13 12:28:13 -0500231
232
Chris Austen0ba649e2015-10-13 12:28:13 -0500233 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
Chris Austen0ba649e2015-10-13 12:28:13 -0500234}
235
236static int handle_ipmi_command(sd_bus_message *m, void *user_data, sd_bus_error
237 *ret_error) {
238 int r = 0;
Jeremy Kerr2564b1a2015-10-27 13:37:17 +0800239 unsigned char sequence, netfn, lun, cmd;
Chris Austen0ba649e2015-10-13 12:28:13 -0500240 const void *request;
241 size_t sz;
242 size_t resplen =MAX_IPMI_BUFFER;
243 unsigned char response[MAX_IPMI_BUFFER];
244
Chris Austen0ba649e2015-10-13 12:28:13 -0500245 memset(response, 0, MAX_IPMI_BUFFER);
246
Jeremy Kerr2564b1a2015-10-27 13:37:17 +0800247 r = sd_bus_message_read(m, "yyyy", &sequence, &netfn, &lun, &cmd);
Chris Austen0ba649e2015-10-13 12:28:13 -0500248 if (r < 0) {
249 fprintf(stderr, "Failed to parse signal message: %s\n", strerror(-r));
250 return -1;
251 }
252
253 r = sd_bus_message_read_array(m, 'y', &request, &sz );
254 if (r < 0) {
255 fprintf(stderr, "Failed to parse signal message: %s\n", strerror(-r));
256 return -1;
257 }
258
Chris Austen99497312015-10-22 13:00:16 -0500259 fprintf(ipmiio, "IPMI Incoming: Seq 0x%02x, NetFn 0x%02x, CMD: 0x%02x \n", sequence, netfn, cmd);
260 hexdump(ipmiio, (void*)request, sz);
Chris Austen0ba649e2015-10-13 12:28:13 -0500261
Chris Austen120f7322015-10-14 23:27:31 -0500262 // Allow the length field to be used for both input and output of the
Chris Austen0ba649e2015-10-13 12:28:13 -0500263 // ipmi call
264 resplen = sz;
265
Chris Austen120f7322015-10-14 23:27:31 -0500266 // Now that we have parsed the entire byte array from the caller
vishwabmcba0bd5f2015-09-30 16:50:23 +0530267 // we can call the ipmi router to do the work...
Chris Austen0ba649e2015-10-13 12:28:13 -0500268 r = ipmi_netfn_router(netfn, cmd, (void *)request, (void *)response, &resplen);
269 if(r != 0)
vishwabmcba0bd5f2015-09-30 16:50:23 +0530270 {
Chris Austen0ba649e2015-10-13 12:28:13 -0500271 fprintf(stderr,"ERROR:[0x%X] handling NetFn:[0x%X], Cmd:[0x%X]\n",r, netfn, cmd);
vishwabmcba0bd5f2015-09-30 16:50:23 +0530272 }
273
Chris Austen99497312015-10-22 13:00:16 -0500274 fprintf(ipmiio, "IPMI Response:\n");
275 hexdump(ipmiio, (void*)response, resplen);
vishwabmcba0bd5f2015-09-30 16:50:23 +0530276
Chris Austen0ba649e2015-10-13 12:28:13 -0500277 // Send the response buffer from the ipmi command
Jeremy Kerr2564b1a2015-10-27 13:37:17 +0800278 r = send_ipmi_message(m, sequence, netfn, lun, cmd, response[0],
279 ((unsigned char *)response) + 1, resplen - 1);
Chris Austen0ba649e2015-10-13 12:28:13 -0500280 if (r < 0) {
281 fprintf(stderr, "Failed to send the response message\n");
282 return -1;
vishwabmcba0bd5f2015-09-30 16:50:23 +0530283 }
284
vishwabmcba0bd5f2015-09-30 16:50:23 +0530285
Chris Austen0ba649e2015-10-13 12:28:13 -0500286 return 0;
vishwabmcba0bd5f2015-09-30 16:50:23 +0530287}
288
Chris Austen0ba649e2015-10-13 12:28:13 -0500289
vishwabmcba0bd5f2015-09-30 16:50:23 +0530290//----------------------------------------------------------------------
291// handler_select
292// Select all the files ending with with .so. in the given diretcory
293// @d: dirent structure containing the file name
294//----------------------------------------------------------------------
295int handler_select(const struct dirent *entry)
296{
297 // To hold ".so" from entry->d_name;
298 char dname_copy[4] = {0};
299
300 // We want to avoid checking for everything and isolate to the ones having
301 // .so in them.
302 if(strstr(entry->d_name, IPMI_PLUGIN_EXTN))
303 {
304 // It is possible that .so could be anywhere in the string but unlikely
Chris Austen120f7322015-10-14 23:27:31 -0500305 // But being careful here. Get the base address of the string, move
vishwabmcba0bd5f2015-09-30 16:50:23 +0530306 // until end and come back 3 steps and that gets what we need.
307 strcpy(dname_copy, (entry->d_name + strlen(entry->d_name)-strlen(IPMI_PLUGIN_EXTN)));
308 if(strcmp(dname_copy, IPMI_PLUGIN_EXTN) == 0)
309 {
310 return 1;
311 }
312 }
313 return 0;
314}
315
316// 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 -0500317// register a callback handler
vishwabmcba0bd5f2015-09-30 16:50:23 +0530318void ipmi_register_callback_handlers(const char* ipmi_lib_path)
319{
320 // For walking the ipmi_lib_path
321 struct dirent **handler_list;
322 int num_handlers = 0;
323
324 // This is used to check and abort if someone tries to register a bad one.
325 void *lib_handler = NULL;
326
327 if(ipmi_lib_path == NULL)
328 {
329 fprintf(stderr,"ERROR; No handlers to be registered for ipmi.. Aborting\n");
330 assert(0);
331 }
332 else
333 {
334 // 1: Open ipmi_lib_path. Its usually "/usr/lib/phosphor-host-ipmid"
335 // 2: Scan the directory for the files that end with .so
Chris Austen120f7322015-10-14 23:27:31 -0500336 // 3: For each one of them, just do a 'dlopen' so that they register
vishwabmcba0bd5f2015-09-30 16:50:23 +0530337 // the handlers for callback routines.
338
339 std::string handler_fqdn = ipmi_lib_path;
Chris Austen120f7322015-10-14 23:27:31 -0500340
vishwabmcba0bd5f2015-09-30 16:50:23 +0530341 // Append a "/" since we need to add the name of the .so. If there is
342 // already a .so, adding one more is not any harm.
343 handler_fqdn += "/";
344
345 num_handlers = scandir(ipmi_lib_path, &handler_list, handler_select, alphasort);
Jeremy Kerr5e8f85e2015-10-27 13:43:54 +0800346 if (num_handlers < 0)
347 return;
348
vishwabmcba0bd5f2015-09-30 16:50:23 +0530349 while(num_handlers--)
350 {
Chris Austen54030262015-10-13 12:30:46 -0500351 handler_fqdn = ipmi_lib_path;
vishwabmcba0bd5f2015-09-30 16:50:23 +0530352 handler_fqdn += handler_list[num_handlers]->d_name;
Chris Austen54030262015-10-13 12:30:46 -0500353 printf("Registering handler:[%s]\n",handler_fqdn.c_str());
354
vishwabmcba0bd5f2015-09-30 16:50:23 +0530355 lib_handler = dlopen(handler_fqdn.c_str(), RTLD_NOW);
356 if(lib_handler == NULL)
357 {
Chris Austen120f7322015-10-14 23:27:31 -0500358 fprintf(stderr,"ERROR opening [%s]: %s\n",
359 handler_fqdn.c_str(), dlerror());
vishwabmcba0bd5f2015-09-30 16:50:23 +0530360 }
361 // Wipe the memory allocated for this particular entry.
362 free(handler_list[num_handlers]);
363 }
364 // Done with all registration.
365 free(handler_list);
366 }
367
368 // TODO : What to be done on the memory that is given by dlopen ?.
369 return;
370}
371
Chris Austen30195fa2015-11-13 14:39:19 -0600372sd_bus *ipmid_get_sd_bus_connection(void) {
373 return bus;
374}
375
vishwabmcba0bd5f2015-09-30 16:50:23 +0530376int main(int argc, char *argv[])
377{
Chris Austen0ba649e2015-10-13 12:28:13 -0500378 sd_bus_slot *slot = NULL;
379 int r;
Chris Austen99497312015-10-22 13:00:16 -0500380 unsigned long tvalue;
381 int c;
382
383
384
385 // This file and subsequient switch is for turning on levels
386 // of trace
387 ipmicmddetails = ipmiio = ipmidbus = fopen("/dev/null", "w");
388
389 while ((c = getopt (argc, argv, "h:d:")) != -1)
390 switch (c) {
391 case 'd':
392 tvalue = strtoul(optarg, NULL, 16);
393 if (1&tvalue) {
394 ipmiio = stdout;
395 }
396 if (2&tvalue) {
397 ipmidbus = stdout;
398 }
399 if (4&tvalue) {
400 ipmicmddetails = stdout;
401 }
402 break;
403 case 'h':
404 case '?':
405 print_usage();
406 return 1;
407 }
Chris Austen0ba649e2015-10-13 12:28:13 -0500408
409
Chris Austen0ba649e2015-10-13 12:28:13 -0500410 /* Connect to system bus */
411 r = sd_bus_open_system(&bus);
412 if (r < 0) {
413 fprintf(stderr, "Failed to connect to system bus: %s\n",
414 strerror(-r));
415 goto finish;
416 }
vishwabmcba0bd5f2015-09-30 16:50:23 +0530417
Chris Austen30195fa2015-11-13 14:39:19 -0600418 // Register all the handlers that provider implementation to IPMI commands.
419 ipmi_register_callback_handlers(HOST_IPMI_LIB_PATH);
420
vishwa36993272015-11-20 12:43:49 -0600421 // Start the Host Services Dbus Objects
422 start_host_service(bus, slot);
423
424 // Watch for BT messages
Chris Austen0ba649e2015-10-13 12:28:13 -0500425 r = sd_bus_add_match(bus, &slot, FILTER, handle_ipmi_command, NULL);
426 if (r < 0) {
427 fprintf(stderr, "Failed: sd_bus_add_match: %s : %s\n", strerror(-r), FILTER);
428 goto finish;
429 }
vishwabmcba0bd5f2015-09-30 16:50:23 +0530430
vishwabmcba0bd5f2015-09-30 16:50:23 +0530431
Chris Austen0ba649e2015-10-13 12:28:13 -0500432 for (;;) {
433 /* Process requests */
Chris Austen0ba649e2015-10-13 12:28:13 -0500434 r = sd_bus_process(bus, NULL);
435 if (r < 0) {
436 fprintf(stderr, "Failed to process bus: %s\n", strerror(-r));
437 goto finish;
438 }
439 if (r > 0) {
440 continue;
441 }
442
443 r = sd_bus_wait(bus, (uint64_t) - 1);
444 if (r < 0) {
445 fprintf(stderr, "Failed to wait on bus: %s\n", strerror(-r));
446 goto finish;
447 }
448 }
449
450finish:
451 sd_bus_slot_unref(slot);
452 sd_bus_unref(bus);
453 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
454
vishwabmcba0bd5f2015-09-30 16:50:23 +0530455}
Chris Austenb071c702015-10-15 00:00:09 -0500456
Chris Austen0012e9b2015-10-22 01:37:46 -0500457// Use a lookup table to find the interface name of a specific sensor
458// This will be used until an alternative is found. this is the first
459// step for mapping IPMI
460int find_interface_property_fru_type(dbus_interface_t *interface, const char *property_name, char *property_value) {
Chris Austenb071c702015-10-15 00:00:09 -0500461
Joel Stanleyf19539e2015-11-25 17:24:05 +1030462 char *str1;
Chris Austen0012e9b2015-10-22 01:37:46 -0500463 sd_bus_error error = SD_BUS_ERROR_NULL;
464 sd_bus_message *reply = NULL, *m=NULL;
Chris Austenb071c702015-10-15 00:00:09 -0500465
466
Chris Austen0012e9b2015-10-22 01:37:46 -0500467 int r;
468
Chris Austen0012e9b2015-10-22 01:37:46 -0500469 r = sd_bus_message_new_method_call(bus,&m,interface->bus,interface->path,"org.freedesktop.DBus.Properties","Get");
470 if (r < 0) {
471 fprintf(stderr, "Failed to create a method call: %s", strerror(-r));
472 fprintf(stderr,"Bus: %s Path: %s Interface: %s \n",
473 interface->bus, interface->path, interface->interface);
474 }
475
476 r = sd_bus_message_append(m, "ss", "org.openbmc.InventoryItem", property_name);
477 if (r < 0) {
478 fprintf(stderr, "Failed to create a input parameter: %s", strerror(-r));
479 fprintf(stderr,"Bus: %s Path: %s Interface: %s \n",
480 interface->bus, interface->path, interface->interface);
481 }
482
483 r = sd_bus_call(bus, m, 0, &error, &reply);
484 if (r < 0) {
485 fprintf(stderr, "Failed to call the method: %s", strerror(-r));
486 goto final;
487 }
488
489 r = sd_bus_message_read(reply, "v", "s", &str1) ;
490 if (r < 0) {
491 fprintf(stderr, "Failed to get a response: %s", strerror(-r));
492 goto final;
493 }
494
495 strcpy(property_value, str1);
496
497final:
498
499 sd_bus_error_free(&error);
500 sd_bus_message_unref(m);
501
502 return r;
503}
Chris Austenb071c702015-10-15 00:00:09 -0500504
Chris Austen41a4b312015-10-25 03:45:42 -0500505
Chris Austenb071c702015-10-15 00:00:09 -0500506// Use a lookup table to find the interface name of a specific sensor
507// This will be used until an alternative is found. this is the first
508// step for mapping IPMI
509int find_openbmc_path(const char *type, const uint8_t num, dbus_interface_t *interface) {
510
511 const char *busname = "org.openbmc.managers.System";
512 const char *objname = "/org/openbmc/managers/System";
513
514 char *str1, *str2, *str3;
515 sd_bus_error error = SD_BUS_ERROR_NULL;
516 sd_bus_message *reply = NULL, *m=NULL;
517
518
519 int r;
520
521 r = sd_bus_message_new_method_call(bus,&m,busname,objname,busname,"getObjectFromByteId");
522 if (r < 0) {
523 fprintf(stderr, "Failed to create a method call: %s", strerror(-r));
524 }
525
526 r = sd_bus_message_append(m, "sy", type, num);
527 if (r < 0) {
528 fprintf(stderr, "Failed to create a input parameter: %s", strerror(-r));
529 }
530
531 // Call the IPMI responder on the bus so the message can be sent to the CEC
532 r = sd_bus_call(bus, m, 0, &error, &reply);
533 if (r < 0) {
534 fprintf(stderr, "Failed to call the method: %s", strerror(-r));
535 goto final;
536 }
537
538
539 r = sd_bus_message_read(reply, "(sss)", &str1, &str2, &str3);
540 if (r < 0) {
541 fprintf(stderr, "Failed to get a response: %s", strerror(-r));
542 goto final;
543 }
544
545 strncpy(interface->bus, str1, MAX_DBUS_PATH);
546 strncpy(interface->path, str2, MAX_DBUS_PATH);
547 strncpy(interface->interface, str3, MAX_DBUS_PATH);
548
549 interface->sensornumber = num;
550
Chris Austenb071c702015-10-15 00:00:09 -0500551final:
552
553 sd_bus_error_free(&error);
554 sd_bus_message_unref(m);
555
556 return r;
557}
558
559
560/////////////////////////////////////////////////////////////////////
561//
562// Routines used by ipmi commands wanting to interact on the dbus
563//
564/////////////////////////////////////////////////////////////////////
565
566
567// Simple set routine because some methods are standard.
568int set_sensor_dbus_state(uint8_t number, const char *method, const char *value) {
569
570
571 dbus_interface_t a;
572 int r;
573 sd_bus_error error = SD_BUS_ERROR_NULL;
574 sd_bus_message *reply = NULL, *m=NULL;
575
Chris Austen99497312015-10-22 13:00:16 -0500576 fprintf(ipmidbus, "Attempting to set a dbus Sensor 0x%02x via %s with a value of %s\n",
Chris Austenb071c702015-10-15 00:00:09 -0500577 number, method, value);
578
579 r = find_openbmc_path("SENSOR", number, &a);
580
Chris Austenb071c702015-10-15 00:00:09 -0500581 r = sd_bus_message_new_method_call(bus,&m,a.bus,a.path,a.interface,method);
582 if (r < 0) {
583 fprintf(stderr, "Failed to create a method call: %s", strerror(-r));
584 }
585
586 r = sd_bus_message_append(m, "s", value);
587 if (r < 0) {
588 fprintf(stderr, "Failed to create a input parameter: %s", strerror(-r));
589 }
590
Chris Austenb071c702015-10-15 00:00:09 -0500591 r = sd_bus_call(bus, m, 0, &error, &reply);
592 if (r < 0) {
593 fprintf(stderr, "Failed to call the method: %s", strerror(-r));
594 }
595
Chris Austenb071c702015-10-15 00:00:09 -0500596 sd_bus_error_free(&error);
597 sd_bus_message_unref(m);
598
599 return 0;
Chris Austenb071c702015-10-15 00:00:09 -0500600}
Chris Austen0130d6e2015-10-15 22:32:36 -0500601
602int set_sensor_dbus_state_v(uint8_t number, const char *method, char *value) {
603
604
605 dbus_interface_t a;
606 int r;
607 sd_bus_error error = SD_BUS_ERROR_NULL;
Joel Stanleyf19539e2015-11-25 17:24:05 +1030608 sd_bus_message *m=NULL;
Chris Austen0130d6e2015-10-15 22:32:36 -0500609
Chris Austen99497312015-10-22 13:00:16 -0500610 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 -0500611 number, method, value);
612
613 r = find_openbmc_path("SENSOR", number, &a);
614
Chris Austen0130d6e2015-10-15 22:32:36 -0500615 r = sd_bus_message_new_method_call(bus,&m,a.bus,a.path,a.interface,method);
616 if (r < 0) {
617 fprintf(stderr, "Failed to create a method call: %s", strerror(-r));
618 }
619
620 r = sd_bus_message_append(m, "v", "s", value);
621 if (r < 0) {
622 fprintf(stderr, "Failed to create a input parameter: %s", strerror(-r));
623 }
624
625
Chris Austen0130d6e2015-10-15 22:32:36 -0500626 r = sd_bus_call(bus, m, 0, &error, NULL);
627 if (r < 0) {
628 fprintf(stderr, "12 Failed to call the method: %s", strerror(-r));
629 }
630
631
Chris Austen0130d6e2015-10-15 22:32:36 -0500632 sd_bus_error_free(&error);
633 sd_bus_message_unref(m);
634
635 return 0;
636}