Пример #1
0
static int64_t opal_ipmi_recv(uint64_t interface,
			      struct opal_ipmi_msg *opal_ipmi_msg, uint64_t *msg_len)
{
	struct ipmi_msg *msg;
	int64_t rc;

	lock(&msgq_lock);
	msg = list_top(&msgq, struct ipmi_msg, link);

	if (!msg) {
		rc = OPAL_EMPTY;
		goto out_unlock;
	}

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

	if (interface != IPMI_DEFAULT_INTERFACE) {
		prerror("IPMI: Invalid interface 0x%llx in opal_ipmi_recv\n", interface);
		rc = OPAL_PARAMETER;
		goto out_del_msg;
	}

	if (*msg_len - sizeof(struct opal_ipmi_msg) < msg->resp_size + 1) {
		rc = OPAL_RESOURCE;
		goto out_del_msg;
	}

	list_del(&msg->link);
	if (list_empty(&msgq))
		opal_update_pending_evt(ipmi_backend->opal_event_ipmi_recv, 0);
	unlock(&msgq_lock);

	opal_ipmi_msg->cmd = msg->cmd;
	opal_ipmi_msg->netfn = msg->netfn;
	opal_ipmi_msg->data[0] = msg->cc;
	memcpy(&opal_ipmi_msg->data[1], msg->data, msg->resp_size);

	prlog(PR_DEBUG, "opal_ipmi_recv(cmd: 0x%02x netfn: 0x%02x resp_size: 0x%02x)\n",
	      msg->cmd, msg->netfn >> 2, msg->resp_size);

	/* Add one as the completion code is returned in the message data */
	*msg_len = msg->resp_size + sizeof(struct opal_ipmi_msg) + 1;
	ipmi_free_msg(msg);

	return OPAL_SUCCESS;

out_del_msg:
	list_del(&msg->link);
	if (list_empty(&msgq))
		opal_update_pending_evt(ipmi_backend->opal_event_ipmi_recv, 0);
	ipmi_free_msg(msg);
out_unlock:
	unlock(&msgq_lock);
	return rc;
}
Пример #2
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;
}
Пример #3
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;
}
Пример #4
0
static void ipmi_wdt_complete(struct ipmi_msg *msg)
{
	if (msg->cmd == IPMI_CMD(IPMI_RESET_WDT) && !msg->user_data)
		schedule_timer(&wdt_timer, msecs_to_tb(
				       (WDT_TIMEOUT - WDT_MARGIN)*100));

	ipmi_free_msg(msg);
}
Пример #5
0
static void ipmi_get_chassis_boot_opt_resp(struct ipmi_msg *msg)
{
	bmc_boot_opt_waiting = false;

	if (msg->cc != IPMI_CC_NO_ERROR) {
		prlog(PR_INFO, "IPMI: IPMI_CHASSIS_GET_BOOT_OPT cmd returned error"
		      " [rc : 0x%x]\n", msg->data[0]);
		ipmi_free_msg(msg);
		return;
	}

	if (msg->resp_size == sizeof(struct ipmi_sys_boot_opt)) {
		bmc_boot_opt_valid = true;
		memcpy(ipmi_sys_boot_opt, msg->data, msg->resp_size);
	} else {
		prlog(PR_WARNING, "IPMI: IPMI_CHASSIS_GET_BOOT_OPT unexpected response size\n");
	}

	ipmi_free_msg(msg);
}
Пример #6
0
static void ipmi_sel_free_msg(struct ipmi_msg *msg)
{
	if (msg == ipmi_sel_panic_msg.msg) {
		lock(&ipmi_sel_panic_msg.lock);
		ipmi_sel_panic_msg.busy = false;
		unlock(&ipmi_sel_panic_msg.lock);
	} else {
		ipmi_free_msg(msg);
	}

	msg = NULL;
}
Пример #7
0
static void get_sel_time_complete(struct ipmi_msg *msg)
{
	struct tm tm;
	le32 result;
	time_t time;

	memcpy(&result, msg->data, 4);
	time = le32_to_cpu(result);
	gmtime_r(&time, &tm);
	rtc_cache_update(&tm);
	time_status = updated;
	ipmi_free_msg(msg);
}
Пример #8
0
static void ipmi_get_bmc_info_resp(struct ipmi_msg *msg)
{
	bmc_info_waiting = false;

	if (msg->cc != IPMI_CC_NO_ERROR) {
		prlog(PR_ERR, "IPMI: IPMI_BMC_GET_DEVICE_ID cmd returned error"
		      " [rc : 0x%x]\n", msg->data[0]);
		return;
	}

	/* ipmi_dev_id has optional fields */
	if (msg->resp_size <= sizeof(struct ipmi_dev_id)) {
		bmc_info_valid = true;
		memcpy(ipmi_dev_id, msg->data, msg->resp_size);
	} else {
		prlog(PR_WARNING, "IPMI: IPMI_BMC_GET_DEVICE_ID unexpected response size\n");
	}

	ipmi_free_msg(msg);
}
Пример #9
0
static void get_bt_caps_complete(struct ipmi_msg *msg)
{
	/* Ignore errors, we'll fallback to using the defaults, no big deal */
	if (msg->data[0] == 0) {
		prlog(PR_DEBUG, "Got illegal BMC BT capability\n");
		goto out;
	}

	if (msg->data[1] != BT_FIFO_LEN) {
		prlog(PR_DEBUG, "Got a input buffer len (%u) cap which differs from the default\n",
				msg->data[1]);
	}

	if (msg->data[2] != BT_FIFO_LEN) {
		prlog(PR_DEBUG, "Got a output buffer len (%u) cap which differs from the default\n",
				msg->data[2]);
	}

	/*
	 * IPMI Spec says that the value for buffer sizes are:
	 * "the largest value allowed in first byte"
	 * Therefore we want to add one to what we get
	 */
	bt.caps.num_requests = msg->data[0];
	bt.caps.input_buf_len = msg->data[1] + 1;
	bt.caps.output_buf_len = msg->data[2] + 1;
	bt.caps.msg_timeout = msg->data[3];
	bt.caps.max_retries = msg->data[4];
	prlog(PR_DEBUG, "BMC BT capabilities received:\n");
	prlog(PR_DEBUG, "buffer sizes: %d input %d output\n",
			bt.caps.input_buf_len, bt.caps.output_buf_len);
	prlog(PR_DEBUG, "number of requests: %d\n", bt.caps.num_requests);
	prlog(PR_DEBUG,  "msg timeout: %d max retries: %d\n",
			bt.caps.msg_timeout, bt.caps.max_retries);

out:
	ipmi_free_msg(msg);
}
Пример #10
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);
}
Пример #11
0
static void get_sel_time_error(struct ipmi_msg *msg)
{
	time_status = error;
	ipmi_free_msg(msg);
}