Esempio n. 1
0
int main(int argc, char *argv[])
{
	static const char *matchfmt =
		"type='signal',"
		"interface='org.freedesktop.DBus.Properties',"
		"member='PropertiesChanged',"
		"arg0='org.openbmc.control.Power',"
		"path='%s',"
		"sender='%s'";
	static const char *usage =
		"Usage: %s OBJECTPATH on|off\n";
	static const size_t LEN = 256;

	sd_bus *conn = NULL;
	sd_event *loop = NULL;
	sd_bus_slot *slot = NULL;
	sd_bus_error error = SD_BUS_ERROR_NULL;
	char *service = NULL;
	int r, dest = -1, state;
	char match[LEN];

	if(argc < 3) {
		fprintf(stderr, usage, argv[0]);
		exit(EXIT_FAILURE);
	}

	if(!strcmp(argv[2], "on"))
		dest = 1;
	if(!strcmp(argv[2], "off"))
		dest = 0;

	if(dest != 0 && dest != 1) {
		fprintf(stderr, usage, argv[0]);
		exit(EXIT_FAILURE);
	}

	r = sd_bus_default_system(&conn);
	if(r < 0) {
		fprintf(stderr, "Error connecting to system bus: %s\n",
				strerror(-r));
		goto finish;
	}

	r = mapper_get_service(conn, argv[1], &service);
	if (r < 0) {
		fprintf(stderr, "Error obtaining host service: %s\n",
				strerror(-r));
		goto finish;
	}

	r = sd_event_default(&loop);
	if (r < 0) {
		fprintf(stderr, "Error obtaining event loop: %s\n",
				strerror(-r));
		goto finish;
	}

	r = sd_bus_attach_event(conn, loop, SD_EVENT_PRIORITY_NORMAL);
	if (r < 0) {
		fprintf(stderr, "Failed to attach system "
				"bus to event loop: %s\n",
				strerror(-r));
		goto finish;
	}

	if(strlen(matchfmt) + strnlen(argv[1], LEN) > LEN) {
		r = -E2BIG;
		fprintf(stderr, "Error adding match rule: %s\n",
				strerror(-r));
		goto finish;
	}

	sprintf(match, matchfmt, argv[1], service);

	r = sd_bus_add_match(conn,
			&slot,
			match,
			callback,
			loop);
	if(r < 0) {
		fprintf(stderr, "Error adding match rule: %s\n",
				strerror(-r));
		goto finish;
	}

	r = sd_bus_get_property_trivial(conn,
			service,
			argv[1],
			"org.openbmc.control.Power",
			"pgood",
			&error,
			'i',
			&state);
	if(r < 0) {
		fprintf(stderr, "Error getting property: %s\n",
				strerror(-r));
		goto finish;
	}

	if(dest == state)
		goto finish;

	r = sd_event_loop(loop);
	if(r < 0) {
		fprintf(stderr, "Error starting event loop: %s\n",
				strerror(-r));
		goto finish;
	}

finish:
	exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
}
//-------------------------------------------------------------------
// Gets called by PowerOff handler when a Soft Power off is requested
//-------------------------------------------------------------------
static int soft_power_off(sd_bus_message *m, void *userdata, sd_bus_error *ret_error)
{
    int64_t bt_resp = -1;
    int rc = 0;
    char *bus_name = NULL;

    // Steps to be taken when we get this.
    //  1: Send a SMS_ATN to the Host
    //  2: Host receives it and sends a GetMsgFlags IPMI command
    //  3: IPMID app handler will respond to that with a MSgFlag with bit:0x2
    //     set indicating we have a message for Host
    //  4: Host sends a GetMsgBuffer command and app handler will respond to
    //     that with a OEM-SEL with certain fields packed indicating to the
    //     host that it do a shutdown of the partitions.
    //  5: Host does the partition shutdown and calls Chassis Power off command
    //  6: App handler handles the command by making a call to ChassisManager
    //     Dbus

    // Now the job is to send the SMS_ATTN.

    // Req message contains the specifics about which method etc that we want to
    // access on which bus, object
    sd_bus_message *response = NULL;

    // Error return mechanism
    sd_bus_error bus_error = SD_BUS_ERROR_NULL;

    // Gets a hook onto either a SYSTEM or SESSION bus
    sd_bus *bus = ipmid_get_sd_bus_connection();
    rc = mapper_get_service(bus, object_name, &bus_name);
    if (rc < 0) {
        fprintf(stderr, "Failed to get %s bus name: %s\n",
                object_name, strerror(-rc));
        goto finish;
    }
    rc = sd_bus_call_method(bus,             // In the System Bus
                            bus_name,        // Service to contact
                            object_name,     // Object path
                            intf_name,       // Interface name
                            "setAttention",  // Method to be called
                            &bus_error,      // object to return error
                            &response,       // Response buffer if any
                            NULL);           // No input arguments
    if(rc < 0)
    {
        fprintf(stderr,"ERROR initiating Power Off:[%s]\n",bus_error.message);
        goto finish;
    }

    // See if we were able to successfully raise SMS_ATN
    rc = sd_bus_message_read(response, "x", &bt_resp);
    if (rc < 0)
    {
        fprintf(stderr, "Failed to get a rc from BT for SMS_ATN: %s\n", strerror(-rc));
        goto finish;
    }

finish:
    sd_bus_error_free(&bus_error);
    response = sd_bus_message_unref(response);
    free(bus_name);

    if(rc < 0)
    {
        return sd_bus_reply_method_return(m, "x", rc);
    }
    else
    {
        return sd_bus_reply_method_return(m, "x", bt_resp);
    }
}