Example #1
0
static int64_t opal_ipmi_send(uint64_t interface,
			      struct opal_ipmi_msg *opal_ipmi_msg, uint64_t msg_len)
{
	struct ipmi_msg *msg;

	if (opal_ipmi_msg->version != OPAL_IPMI_MSG_FORMAT_VERSION_1) {
		prerror("OPAL IPMI: Incorrect version\n");
		return OPAL_UNSUPPORTED;
	}

	msg_len -= sizeof(struct opal_ipmi_msg);
	if (msg_len > IPMI_MAX_REQ_SIZE) {
		prerror("OPAL IPMI: Invalid request length\n");
		return OPAL_PARAMETER;
	}

	prlog(PR_DEBUG, "opal_ipmi_send(cmd: 0x%02x netfn: 0x%02x len: 0x%02llx)\n",
	       opal_ipmi_msg->cmd, opal_ipmi_msg->netfn >> 2, msg_len);

	msg = ipmi_mkmsg(interface,
			 IPMI_CODE(opal_ipmi_msg->netfn >> 2, opal_ipmi_msg->cmd),
			 opal_send_complete, NULL, opal_ipmi_msg->data,
			 msg_len, IPMI_MAX_RESP_SIZE);
	if (!msg)
		return OPAL_RESOURCE;

	msg->complete = opal_send_complete;
	msg->error = opal_send_complete;
	return ipmi_queue_msg(msg);
}
Example #2
0
static int fru_write(void)
{
	struct ipmi_msg *msg;
	int len;

	/* We allocate FRU_DATA_SIZE + 5 bytes for the message:
	 * - 3 bytes for the the write FRU command header
	 * - FRU_DATA_SIZE bytes for FRU data
	 * - 2 bytes for offset & bytes remaining count
	 */
	msg = ipmi_mkmsg(IPMI_DEFAULT_INTERFACE, IPMI_WRITE_FRU,
			 fru_write_complete, NULL, NULL, FRU_DATA_SIZE + 5, 2);
	if (!msg)
		return OPAL_RESOURCE;

	msg->data[0] = fru_dev_id;	/* FRU Device ID */
	msg->data[1] = 0x0;		/* Offset LSB (we always write a new common header) */
	msg->data[2] = 0x0;		/* Offset MSB */
	len = fru_add(&msg->data[3], FRU_DATA_SIZE);

	if (len < 0)
		return len;

	/* Three bytes for the actual FRU Data Command */
	msg->data[WRITE_INDEX] = 0;
	msg->data[REMAINING] = len;
	msg->req_size = min(len + 3, IPMI_MAX_REQ_SIZE);
	return ipmi_queue_msg(msg);
}
Example #3
0
int ipmi_get_chassis_boot_opt_request(void)
{
	int rc;
	struct ipmi_msg *msg;
	uint8_t req[] = {
		0x62, /* OEM parameter (SBE Validation on astbmc) */
		0x00, /* no set selector */
		0x00, /* no block selector */
	};

	ipmi_sys_boot_opt = zalloc(sizeof(struct ipmi_sys_boot_opt));
	assert(ipmi_sys_boot_opt);

	msg = ipmi_mkmsg(IPMI_DEFAULT_INTERFACE, IPMI_CHASSIS_GET_BOOT_OPT,
			 ipmi_get_chassis_boot_opt_resp, NULL, req,
			 sizeof(req), sizeof(struct ipmi_sys_boot_opt));
	if (!msg) {
		free(ipmi_sys_boot_opt);
		return OPAL_NO_MEM;
	}

	msg->error = ipmi_get_chassis_boot_opt_resp;
	prlog(PR_INFO, "IPMI: Requesting IPMI_CHASSIS_GET_BOOT_OPT\n");
	rc = ipmi_queue_msg(msg);
	if (rc) {
		prlog(PR_ERR, "IPMI: Failed to queue IPMI_CHASSIS_GET_BOOT_OPT\n");
		free(ipmi_sys_boot_opt);
		ipmi_free_msg(msg);
		return rc;
	}

	bmc_boot_opt_waiting = true;
	return rc;
}
Example #4
0
int ipmi_elog_commit(struct errorlog *elog_buf)
{
	struct ipmi_msg *msg;

	/* Only log events that needs attention */
	if (elog_buf->event_severity <
			OPAL_PREDICTIVE_ERR_FAULT_RECTIFY_REBOOT ||
			elog_buf->elog_origin != ORG_SAPPHIRE) {
		prlog(PR_INFO, "dropping non severe PEL event\n");
		opal_elog_complete(elog_buf, true);
		return 0;
	}

	/*
	 * We pass a large request size in to mkmsg so that we have a
	 * large enough allocation to reuse the message to pass the
	 * PEL data via a series of partial add commands.
	 */
	msg = ipmi_sel_alloc_msg(elog_buf);
	if (!msg) {
		opal_elog_complete(elog_buf, false);
		return OPAL_RESOURCE;
	}

	msg->error = ipmi_elog_error;
	msg->req_size = 0;
	if (elog_buf->event_severity == OPAL_ERROR_PANIC)
		ipmi_queue_msg_sync(msg);
	else
		ipmi_queue_msg(msg);

	return 0;
}
Example #5
0
int ipmi_get_bmc_info_request(void)
{
	int rc;
	struct ipmi_msg *msg;

	ipmi_dev_id = zalloc(sizeof(struct ipmi_dev_id));
	assert(ipmi_dev_id);

	msg = ipmi_mkmsg(IPMI_DEFAULT_INTERFACE, IPMI_BMC_GET_DEVICE_ID,
			 ipmi_get_bmc_info_resp, NULL, NULL,
			 0, sizeof(struct ipmi_dev_id));
	if (!msg)
		return OPAL_NO_MEM;

	msg->error = ipmi_get_bmc_info_resp;
	prlog(PR_INFO, "IPMI: Requesting IPMI_BMC_GET_DEVICE_ID\n");
	rc = ipmi_queue_msg(msg);
	if (rc) {
		prlog(PR_ERR, "IPMI: Failed to queue IPMI_BMC_GET_DEVICE_ID\n");
		ipmi_free_msg(msg);
		return rc;
	}

	bmc_info_waiting = true;
	return rc;
}
Example #6
0
int ipmi_set_power_state(uint8_t system, uint8_t device)
{
	struct ipmi_msg *msg;
	struct {
		uint8_t system;
		uint8_t device;
	} power_state;

	if (!ipmi_present())
		return OPAL_CLOSED;

	power_state.system = system;
	power_state.device = device;

	if (system != IPMI_PWR_NOCHANGE)
		power_state.system |= 0x80;
	if (device != IPMI_PWR_NOCHANGE)
		power_state.device |= 0x80;

	msg = ipmi_mkmsg_simple(IPMI_SET_POWER_STATE, &power_state,
				sizeof(power_state));

	if (!msg)
		return OPAL_HARDWARE;

	prlog(PR_INFO, "IPMI: setting power state: sys %02x, dev %02x\n",
			power_state.system, power_state.device);

	return ipmi_queue_msg(msg);
}
Example #7
0
static void ipmi_elog_error(struct ipmi_msg *msg)
{
	if (msg->cc == IPMI_LOST_ARBITRATION_ERR)
		/* Retry due to SEL erase */
		ipmi_queue_msg(msg);
	else {
		opal_elog_complete(msg->user_data, false);
		ipmi_sel_free_msg(msg);
	}
}
Example #8
0
static int64_t ipmi_set_sel_time(uint32_t _tv)
{
	struct ipmi_msg *msg;
	const le32 tv = cpu_to_le32(_tv);

	msg = ipmi_mkmsg_simple(IPMI_SET_SEL_TIME, (void*)&tv, sizeof(tv));
	if (!msg)
		return OPAL_HARDWARE;

	return ipmi_queue_msg(msg);
}
Example #9
0
static int64_t ipmi_get_sel_time(void)
{
	struct ipmi_msg *msg;

	msg = ipmi_mkmsg(IPMI_DEFAULT_INTERFACE, IPMI_GET_SEL_TIME,
			 get_sel_time_complete, NULL, NULL, 0, 4);
	if (!msg)
		return OPAL_HARDWARE;

	msg->error = get_sel_time_error;

	return ipmi_queue_msg(msg);
}
Example #10
0
static void get_bt_caps(void)
{

	struct ipmi_msg *bmc_caps;
	/*
	 * Didn't sent a message, now is a good time to ask the BMC for its
	 * capabilities.
	 */
	bmc_caps = ipmi_mkmsg(IPMI_DEFAULT_INTERFACE, IPMI_GET_BT_CAPS,
			get_bt_caps_complete, NULL, NULL, 0, sizeof(struct bt_caps));
	if (!bmc_caps)
		prerror("Couldn't create BMC BT capabilities msg\n");

	if (bmc_caps && ipmi_queue_msg(bmc_caps))
		prerror("Couldn't enqueue request for BMC BT capabilities\n");

	/* Ignore errors, we'll fallback to using the defaults, no big deal */
}
Example #11
0
static void set_wdt(uint8_t action, uint16_t count, uint8_t pretimeout)
{
	struct ipmi_msg *ipmi_msg;

	ipmi_msg = ipmi_mkmsg(IPMI_DEFAULT_INTERFACE, IPMI_SET_WDT,
			      ipmi_wdt_complete, NULL, NULL, 6, 0);
	if (!ipmi_msg) {
		prerror("Unable to allocate set wdt message\n");
		return;
	}
	ipmi_msg->error = ipmi_wdt_complete;
	ipmi_msg->data[0] = TIMER_USE_POST |
		TIMER_USE_DONT_LOG; 			/* Timer Use */
	ipmi_msg->data[1] = action;			/* Timer Actions */
	ipmi_msg->data[2] = pretimeout;			/* Pre-timeout Interval */
	ipmi_msg->data[3] = 0;				/* Timer Use Flags */
	ipmi_msg->data[4] = count & 0xff;		/* Initial countdown (lsb) */
	ipmi_msg->data[5] = (count >> 8) & 0xff;	/* Initial countdown (msb) */
	ipmi_queue_msg(ipmi_msg);
}
Example #12
0
int ipmi_chassis_control(uint8_t request)
{
	struct ipmi_msg *msg;

	if (!ipmi_present())
		return OPAL_CLOSED;

	if (request > IPMI_CHASSIS_SOFT_SHUTDOWN)
		return OPAL_PARAMETER;

	msg = ipmi_mkmsg_simple(IPMI_CHASSIS_CONTROL, &request,
				sizeof(request));
	if (!msg)
		return OPAL_HARDWARE;

	prlog(PR_INFO, "IPMI: sending chassis control request 0x%02x\n",
			request);

	return ipmi_queue_msg(msg);
}
Example #13
0
static int fru_add(u8 *buf, int size)
{
	int len;
	char short_version[MAX_STR_LEN + 1];
	struct common_header common_hdr;
	struct product_info info = {
		.manufacturer = (char *) "IBM",
		.product = (char *) "skiboot",
		.part_no = (char *) "",
		.serial_no = (char *) "",
		.asset_tag = (char *) "",
	};

	if (size < sizeof(common_hdr))
		return OPAL_PARAMETER;

	/* We currently only support adding the version number at the
	 * product information offset. We choose an offset of 64 bytes
	 * because that's what the standard recommends. */
	common_hdr.version = 1;
	common_hdr.internal_offset = 0;
	common_hdr.chassis_offset = 0;
	common_hdr.board_offset = 0;
	common_hdr.product_offset = 64/8;
	common_hdr.multirecord_offset = 0;
	common_hdr.pad = 0;
	common_hdr.checksum = fru_checksum((u8 *) &common_hdr, sizeof(common_hdr) - 1);
	memcpy(buf, &common_hdr, sizeof(common_hdr));

	info.version = short_version;
	if (!strncmp(version, "skiboot-", 8))
		strncpy(info.version, &version[8], MAX_STR_LEN + 1);
	else
		strncpy(info.version, version, MAX_STR_LEN + 1);

	if (info.version[MAX_STR_LEN] != '\0')
		info.version[MAX_STR_LEN - 1] = '+';
	info.version[MAX_STR_LEN] = '\0';

	len = fru_fill_product_info(&buf[64], &info, size - 64);
	if (len < 0)
		return OPAL_PARAMETER;

	return len + 64;
}

static void fru_write_complete(struct ipmi_msg *msg)
{
	u8 write_count = msg->data[0];
	u16 offset;

	msg->data[WRITE_INDEX] += write_count;
	msg->data[REMAINING] -= write_count;
	if (msg->data[REMAINING] == 0)
		goto out;

	offset = msg->data[WRITE_INDEX];
	ipmi_init_msg(msg, IPMI_DEFAULT_INTERFACE, IPMI_WRITE_FRU,
		      fru_write_complete, NULL,
		      MIN(msg->data[REMAINING] + 3, IPMI_MAX_REQ_SIZE), 2);

	memmove(&msg->data[3], &msg->data[offset + 3], msg->req_size - 3);

	msg->data[0] = fru_dev_id;     		/* FRU Device ID */
	msg->data[1] = offset & 0xff;		/* Offset LSB */
	msg->data[2] = (offset >> 8) & 0xff;	/* Offset MSB */

	ipmi_queue_msg(msg);

	return;

out:
	ipmi_free_msg(msg);
}