198a23840SMatthew Barth #include "globalhandler.h"
237af7331SPatrick Williams #include "host-ipmid/ipmid-api.h"
398a23840SMatthew Barth #include <stdio.h>
498a23840SMatthew Barth #include <string.h>
598a23840SMatthew Barth #include <stdint.h>
698a23840SMatthew Barth 
798a23840SMatthew Barth const char  *control_object_name  =  "/org/openbmc/control/bmc0";
898a23840SMatthew Barth const char  *control_intf_name    =  "org.openbmc.control.Bmc";
998a23840SMatthew Barth 
1098a23840SMatthew Barth const char  *objectmapper_service_name =  "org.openbmc.ObjectMapper";
1198a23840SMatthew Barth const char  *objectmapper_object_name  =  "/org/openbmc/ObjectMapper";
1298a23840SMatthew Barth const char  *objectmapper_intf_name    =  "org.openbmc.ObjectMapper";
1398a23840SMatthew Barth 
1498a23840SMatthew Barth void register_netfn_global_functions() __attribute__((constructor));
1598a23840SMatthew Barth 
1698a23840SMatthew Barth int obj_mapper_get_connection(char** buf, const char* obj_path)
1798a23840SMatthew Barth {
1898a23840SMatthew Barth     sd_bus_error error = SD_BUS_ERROR_NULL;
1998a23840SMatthew Barth     sd_bus_message *m = NULL;
2098a23840SMatthew Barth     sd_bus *bus = NULL;
2198a23840SMatthew Barth     char *temp_buf = NULL, *intf = NULL;
2298a23840SMatthew Barth     size_t buf_size = 0;
2398a23840SMatthew Barth     int r;
2498a23840SMatthew Barth 
2598a23840SMatthew Barth     //Get the system bus where most system services are provided.
2698a23840SMatthew Barth     bus = ipmid_get_sd_bus_connection();
2798a23840SMatthew Barth 
2898a23840SMatthew Barth     /*
2998a23840SMatthew Barth      * Bus, service, object path, interface and method are provided to call
3098a23840SMatthew Barth      * the method.
3198a23840SMatthew Barth      * Signatures and input arguments are provided by the arguments at the
3298a23840SMatthew Barth      * end.
3398a23840SMatthew Barth      */
3498a23840SMatthew Barth     r = sd_bus_call_method(bus,
3598a23840SMatthew Barth             objectmapper_service_name,                      /* service to contact */
3698a23840SMatthew Barth             objectmapper_object_name,                       /* object path */
3798a23840SMatthew Barth             objectmapper_intf_name,                         /* interface name */
3898a23840SMatthew Barth             "GetObject",                                    /* method name */
3998a23840SMatthew Barth             &error,                                         /* object to return error in */
4098a23840SMatthew Barth             &m,                                             /* return message on success */
4198a23840SMatthew Barth             "s",                                            /* input signature */
4298a23840SMatthew Barth             obj_path                                        /* first argument */
4398a23840SMatthew Barth             );
4498a23840SMatthew Barth 
4598a23840SMatthew Barth     if (r < 0) {
4698a23840SMatthew Barth         fprintf(stderr, "Failed to issue method call: %s\n", error.message);
4798a23840SMatthew Barth         goto finish;
4898a23840SMatthew Barth     }
4998a23840SMatthew Barth 
5098a23840SMatthew Barth     // Get the key, aka, the connection name
5198a23840SMatthew Barth     sd_bus_message_read(m, "a{sas}", 1, &temp_buf, 1, &intf);
5298a23840SMatthew Barth 
5398a23840SMatthew Barth 	/*
5498a23840SMatthew Barth      * TODO: check the return code. Currently for no reason the message
5598a23840SMatthew Barth      * parsing of object mapper is always complaining about
5698a23840SMatthew Barth      * "Device or resource busy", but the result seems OK for now. Need
5798a23840SMatthew Barth      *  further checks.
5898a23840SMatthew Barth      */
5998a23840SMatthew Barth 
6098a23840SMatthew Barth     buf_size = strlen(temp_buf) + 1;
6198a23840SMatthew Barth     printf("IPMID connection name: %s\n", temp_buf);
6298a23840SMatthew Barth     *buf = (char*)malloc(buf_size);
6398a23840SMatthew Barth 
6498a23840SMatthew Barth     if (*buf == NULL) {
6598a23840SMatthew Barth         fprintf(stderr, "Malloc failed for warm reset");
6698a23840SMatthew Barth         r = -1;
6798a23840SMatthew Barth         goto finish;
6898a23840SMatthew Barth     }
6998a23840SMatthew Barth 
7098a23840SMatthew Barth     memcpy(*buf, temp_buf, buf_size);
7198a23840SMatthew Barth 
7298a23840SMatthew Barth finish:
7398a23840SMatthew Barth     sd_bus_error_free(&error);
7498a23840SMatthew Barth     sd_bus_message_unref(m);
7598a23840SMatthew Barth 
7698a23840SMatthew Barth     return r;
7798a23840SMatthew Barth }
7898a23840SMatthew Barth 
79*bc759884SNan Li 
80*bc759884SNan Li int dbus_reset(const char *method)
8198a23840SMatthew Barth {
8298a23840SMatthew Barth     sd_bus_error error = SD_BUS_ERROR_NULL;
8398a23840SMatthew Barth     sd_bus_message *m = NULL;
8498a23840SMatthew Barth     sd_bus *bus = NULL;
8598a23840SMatthew Barth     char* connection = NULL;
868b470052SMatthew Barth     int r;
8798a23840SMatthew Barth 
8898a23840SMatthew Barth     r = obj_mapper_get_connection(&connection, control_object_name);
8998a23840SMatthew Barth     if (r < 0) {
9098a23840SMatthew Barth         fprintf(stderr, "Failed to get connection, return value: %d.\n", r);
9198a23840SMatthew Barth         goto finish;
9298a23840SMatthew Barth     }
9398a23840SMatthew Barth 
9498a23840SMatthew Barth     printf("connection: %s\n", connection);
9598a23840SMatthew Barth 
9698a23840SMatthew Barth     // Open the system bus where most system services are provided.
9798a23840SMatthew Barth     bus = ipmid_get_sd_bus_connection();
9898a23840SMatthew Barth 
9998a23840SMatthew Barth     /*
10098a23840SMatthew Barth      * Bus, service, object path, interface and method are provided to call
10198a23840SMatthew Barth      * the method.
10298a23840SMatthew Barth      * Signatures and input arguments are provided by the arguments at the
10398a23840SMatthew Barth      * end.
10498a23840SMatthew Barth      */
10598a23840SMatthew Barth     r = sd_bus_call_method(bus,
10698a23840SMatthew Barth             connection,                                /* service to contact */
10798a23840SMatthew Barth             control_object_name,                       /* object path */
10898a23840SMatthew Barth             control_intf_name,                         /* interface name */
109*bc759884SNan Li             method,                               /* method name */
11098a23840SMatthew Barth             &error,                                    /* object to return error in */
11198a23840SMatthew Barth             &m,                                        /* return message on success */
11298a23840SMatthew Barth             NULL,
11398a23840SMatthew Barth             NULL
11498a23840SMatthew Barth             );
11598a23840SMatthew Barth 
11698a23840SMatthew Barth     if (r < 0) {
11798a23840SMatthew Barth         fprintf(stderr, "Failed to issue method call: %s\n", error.message);
11898a23840SMatthew Barth         goto finish;
11998a23840SMatthew Barth     }
12098a23840SMatthew Barth 
12198a23840SMatthew Barth finish:
12298a23840SMatthew Barth     sd_bus_error_free(&error);
12398a23840SMatthew Barth     sd_bus_message_unref(m);
12498a23840SMatthew Barth     free(connection);
12598a23840SMatthew Barth 
12698a23840SMatthew Barth     return r;
12798a23840SMatthew Barth }
12898a23840SMatthew Barth 
12998a23840SMatthew Barth ipmi_ret_t ipmi_global_warm_reset(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
13098a23840SMatthew Barth                               ipmi_request_t request, ipmi_response_t response,
13198a23840SMatthew Barth                               ipmi_data_len_t data_len, ipmi_context_t context)
13298a23840SMatthew Barth {
13398a23840SMatthew Barth     printf("Handling GLOBAL warmReset Netfn:[0x%X], Cmd:[0x%X]\n",netfn, cmd);
13498a23840SMatthew Barth 
13598a23840SMatthew Barth     // TODO: call the correct dbus method for warmReset.
136*bc759884SNan Li     dbus_reset("warmReset");
13798a23840SMatthew Barth 
13898a23840SMatthew Barth     // Status code.
13998a23840SMatthew Barth     ipmi_ret_t rc = IPMI_CC_OK;
14098a23840SMatthew Barth     *data_len = 0;
14198a23840SMatthew Barth     return rc;
14298a23840SMatthew Barth }
14398a23840SMatthew Barth 
144*bc759884SNan Li ipmi_ret_t ipmi_global_cold_reset(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
145*bc759884SNan Li                               ipmi_request_t request, ipmi_response_t response,
146*bc759884SNan Li                               ipmi_data_len_t data_len, ipmi_context_t context)
147*bc759884SNan Li {
148*bc759884SNan Li     printf("Handling GLOBAL coldReset Netfn:[0x%X], Cmd:[0x%X]\n",netfn, cmd);
149*bc759884SNan Li 
150*bc759884SNan Li     // TODO: call the correct dbus method for coldReset.
151*bc759884SNan Li     dbus_reset("coldReset");
152*bc759884SNan Li 
153*bc759884SNan Li     // Status code.
154*bc759884SNan Li     ipmi_ret_t rc = IPMI_CC_OK;
155*bc759884SNan Li     *data_len = 0;
156*bc759884SNan Li     return rc;
157*bc759884SNan Li }
15898a23840SMatthew Barth 
15998a23840SMatthew Barth void register_netfn_global_functions()
16098a23840SMatthew Barth {
161*bc759884SNan Li     printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_APP, IPMI_CMD_COLD_RESET);
162*bc759884SNan Li     ipmi_register_callback(NETFUN_APP, IPMI_CMD_COLD_RESET, NULL, ipmi_global_cold_reset);
163*bc759884SNan Li 
16498a23840SMatthew Barth     printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_APP, IPMI_CMD_WARM_RESET);
16598a23840SMatthew Barth     ipmi_register_callback(NETFUN_APP, IPMI_CMD_WARM_RESET, NULL, ipmi_global_warm_reset);
16698a23840SMatthew Barth 
16798a23840SMatthew Barth     return;
16898a23840SMatthew Barth }
169