summaryrefslogtreecommitdiffstats
path: root/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/bic/bic.c
diff options
context:
space:
mode:
Diffstat (limited to 'meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/bic/bic.c')
-rw-r--r--meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/bic/bic.c466
1 files changed, 466 insertions, 0 deletions
diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/bic/bic.c b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/bic/bic.c
new file mode 100644
index 0000000..55cd56b
--- /dev/null
+++ b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/bic/bic.c
@@ -0,0 +1,466 @@
+/*
+ *
+ * Copyright 2015-present Facebook. All Rights Reserved.
+ *
+ * This file contains code to support IPMI2.0 Specificaton available @
+ * http://www.intel.com/content/www/us/en/servers/ipmi/ipmi-specifications.html
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdio.h>
+#include <stdint.h>
+#include <fcntl.h>
+#include "bic.h"
+
+#define FRUID_READ_COUNT_MAX 0x30
+#define SDR_READ_COUNT_MAX 0x1A
+
+enum {
+ IPMB_BUS_SLOT1 = 3,
+ IPMB_BUS_SLOT2 = 1,
+ IPMB_BUS_SLOT3 = 7,
+ IPMB_BUS_SLOT4 = 5,
+};
+
+#pragma pack(push, 1)
+typedef struct _sdr_rec_hdr_t {
+ uint16_t rec_id;
+ uint8_t ver;
+ uint8_t type;
+ uint8_t len;
+} sdr_rec_hdr_t;
+#pragma pack(pop)
+
+// Common IPMB Wrapper function
+
+static int
+get_ipmb_bus_id(uint8_t slot_id) {
+ int bus_id;
+
+ switch(slot_id) {
+ case 1:
+ bus_id = IPMB_BUS_SLOT1;
+ break;
+ case 2:
+ bus_id = IPMB_BUS_SLOT2;
+ break;
+ case 3:
+ bus_id = IPMB_BUS_SLOT3;
+ break;
+ case 4:
+ bus_id = IPMB_BUS_SLOT4;
+ break;
+ default:
+ bus_id = -1;
+ break;
+ }
+
+ return bus_id;
+}
+
+static int
+bic_ipmb_wrapper(uint8_t slot_id, uint8_t netfn, uint8_t cmd,
+ uint8_t *txbuf, uint8_t txlen,
+ uint8_t *rxbuf, uint8_t *rxlen) {
+ ipmb_req_t *req;
+ ipmb_res_t *res;
+ uint8_t rbuf[MAX_IPMB_RES_LEN] = {0};
+ uint8_t tbuf[MAX_IPMB_RES_LEN] = {0};
+ uint8_t tlen = 0;
+ uint8_t rlen = 0;
+ int count = 0;
+ int i = 0;
+ int ret;
+ uint8_t bus_id;
+
+ ret = get_ipmb_bus_id(slot_id);
+ if (ret < 0) {
+ printf("bic_ipmb_wrapper: Wrong Slot ID %d\n", slot_id);
+ return ret;
+ }
+
+ bus_id = (uint8_t) ret;
+
+ req = (ipmb_req_t*)tbuf;
+
+ req->res_slave_addr = BRIDGE_SLAVE_ADDR << 1;
+ req->netfn_lun = netfn << LUN_OFFSET;
+ req->hdr_cksum = req->res_slave_addr +
+ req->netfn_lun;
+ req->hdr_cksum = ZERO_CKSUM_CONST - req->hdr_cksum;
+
+ req->req_slave_addr = BMC_SLAVE_ADDR << 1;
+ req->seq_lun = 0x00;
+ req->cmd = cmd;
+
+ //copy the data to be send
+ if (txlen) {
+ memcpy(req->data, txbuf, txlen);
+ }
+
+ tlen = IPMB_HDR_SIZE + IPMI_REQ_HDR_SIZE + txlen;
+
+ // Invoke IPMB library handler
+ lib_ipmb_handle(bus_id, tbuf, tlen, &rbuf, &rlen);
+ if (rlen == 0) {
+ printf("bic_ipmb_wrapper: Zero bytes received\n");
+ return -1;
+ }
+
+ // Handle IPMB response
+ res = (ipmb_res_t*) rbuf;
+
+ if (res->cc) {
+ printf("bic_ipmb_wrapper: Completion Code: 0x%X\n", res->cc);
+ return -1;
+ }
+
+ // copy the received data back to caller
+ *rxlen = rlen - IPMB_HDR_SIZE - IPMI_RESP_HDR_SIZE;
+ memcpy(rxbuf, res->data, *rxlen);
+
+ return 0;
+}
+
+// Get Device ID
+int
+bic_get_dev_id(uint8_t slot_id, ipmi_dev_id_t *dev_id) {
+ uint8_t rlen = 0;
+ int ret;
+
+ ret = bic_ipmb_wrapper(slot_id, NETFN_APP_REQ, CMD_APP_GET_DEVICE_ID, NULL, 0, (uint8_t *) dev_id, &rlen);
+
+ return ret;
+}
+
+// Get GPIO value and configuration
+int
+bic_get_gpio(uint8_t slot_id, bic_gpio_t *gpio) {
+ uint8_t rlen = 0;
+ int ret;
+
+ ret = bic_ipmb_wrapper(slot_id, NETFN_OEM_1S_REQ, CMD_OEM_1S_GET_GPIO, NULL, 0, (uint8_t*) gpio, &rlen);
+
+ return ret;
+}
+
+int
+bic_get_gpio_config(uint8_t slot_id, uint8_t gpio, bic_gpio_config_t *gpio_config) {
+ uint8_t tbuf[4] = {0};
+ uint8_t rlen = 0;
+ uint8_t tlen = 0;
+ uint32_t pin;
+ int ret;
+
+ pin = 1 << gpio;
+
+ tbuf[0] = pin & 0xFF;
+ tbuf[1] = (pin >> 8) & 0xFF;
+ tbuf[2] = (pin >> 16) & 0xFF;
+ tbuf[3] = (pin >> 24) & 0xFF;
+
+ tlen = 4;
+
+ ret = bic_ipmb_wrapper(slot_id, NETFN_OEM_1S_REQ, CMD_OEM_1S_GET_GPIO_CONFIG, tbuf, tlen, (uint8_t *) gpio_config, &rlen);
+
+ return ret;
+}
+
+int
+bic_set_gpio_config(uint8_t slot_id, uint8_t gpio, bic_gpio_config_t *gpio_config) {
+ uint8_t tbuf[5] = {0};
+ uint8_t rlen = 0;
+ uint8_t tlen = 0;
+ uint32_t pin;
+ uint8_t res;
+ int ret;
+
+ pin = 1 << gpio;
+
+ tbuf[0] = pin & 0xFF;
+ tbuf[1] = (pin >> 8) & 0xFF;
+ tbuf[2] = (pin >> 16) & 0xFF;
+ tbuf[3] = (pin >> 24) & 0xFF;
+ tbuf[4] = (*(uint8_t *) gpio_config) & 0x1F;
+
+ tlen = 5;
+
+ ret = bic_ipmb_wrapper(slot_id, NETFN_OEM_1S_REQ, CMD_OEM_1S_SET_GPIO_CONFIG,
+ tbuf, tlen, &res, &rlen);
+ return ret;
+}
+
+// Get BIC Configuration
+int
+bic_get_config(uint8_t slot_id, bic_config_t *cfg) {
+ uint8_t rlen = 0;
+ int ret;
+
+ ret = bic_ipmb_wrapper(slot_id, NETFN_OEM_1S_REQ, CMD_OEM_1S_GET_CONFIG,
+ NULL, 0x00, (uint8_t *) cfg, &rlen);
+ return ret;
+}
+
+// Set BIC Configuration
+int
+bic_set_config(uint8_t slot_id, bic_config_t *cfg) {
+ uint8_t rlen = 0;
+ uint8_t rbuf[4] = {0};
+ int ret;
+
+ ret = bic_ipmb_wrapper(slot_id, NETFN_OEM_1S_REQ, CMD_OEM_1S_SET_CONFIG,
+ (uint8_t *) cfg, 1, rbuf, &rlen);
+ return ret;
+}
+
+// Read POST Buffer
+int
+bic_get_post_buf(uint8_t slot_id, uint8_t *buf, uint8_t *len) {
+ int ret;
+
+ ret = bic_ipmb_wrapper(slot_id, NETFN_OEM_1S_REQ, CMD_OEM_1S_GET_POST_BUF, NULL, 0, buf, len);
+
+ return ret;
+}
+
+// Read 1S server's FRUID
+int
+bic_get_fruid_info(uint8_t slot_id, uint8_t fru_id, ipmi_fruid_info_t *info) {
+ int ret;
+ uint8_t rlen = 0;
+
+ ret = bic_ipmb_wrapper(slot_id, NETFN_STORAGE_REQ, CMD_STORAGE_GET_FRUID_INFO, &fru_id, 1, (uint8_t *) info, &rlen);
+
+ return ret;
+}
+
+static int
+_read_fruid(uint8_t slot_id, uint8_t fru_id, uint32_t offset, uint8_t count, uint8_t *rbuf, uint8_t *rlen) {
+ int ret;
+ uint8_t tbuf[4] = {0};
+ uint8_t tlen = 0;
+
+ tbuf[0] = fru_id;
+ tbuf[1] = offset & 0xFF;
+ tbuf[2] = (offset >> 8) & 0xFF;
+ tbuf[3] = count;
+
+ ret = bic_ipmb_wrapper(slot_id, NETFN_STORAGE_REQ, CMD_STORAGE_READ_FRUID_DATA, tbuf, 4, rbuf, rlen);
+
+ return ret;
+}
+
+int
+bic_read_fruid(uint8_t slot_id, uint8_t fru_id, const char *path) {
+ int ret;
+ uint32_t nread;
+ uint32_t offset;
+ uint8_t count;
+ uint8_t rbuf[256] = {0};
+ uint8_t rlen = 0;
+ int fd;
+ ipmi_fruid_info_t info;
+
+ // Remove the file if exists already
+ unlink(path);
+
+ // Open the file exclusively for write
+ fd = open(path, O_WRONLY | O_CREAT | O_EXCL, 0666);
+ if (fd < 0) {
+ printf("bic_read_fruid: open fails for path: %s\n", path);
+ goto error_exit;
+ }
+
+ // Read the FRUID information
+ ret = bic_get_fruid_info(slot_id, fru_id, &info);
+ if (ret) {
+ printf("bic_read_fruid: bic_read_fruid_info returns %d\n", ret);
+ goto error_exit;
+ }
+
+ // Indicates the size of the FRUID
+ nread = (info.size_msb << 8) + (info.size_lsb);
+
+ // Read chunks of FRUID binary data in a loop
+ offset = 0;
+ while (nread > 0) {
+ if (nread > FRUID_READ_COUNT_MAX) {
+ count = FRUID_READ_COUNT_MAX;
+ } else {
+ count = nread;
+ }
+
+ ret = _read_fruid(slot_id, fru_id, offset, count, rbuf, &rlen);
+ if (ret) {
+ printf("bic_read_fruid: ipmb_wrapper fails\n");
+ goto error_exit;
+ }
+
+ // Ignore the first byte as it indicates length of response
+ write(fd, &rbuf[1], rlen-1);
+
+ // Update offset
+ offset += (rlen-1);
+ nread -= (rlen-1);
+ }
+
+error_exit:
+ if (fd > 0 ) {
+ close(fd);
+ }
+
+ return ret;
+}
+
+// Read System Event Log (SEL)
+int
+bic_get_sel_info(uint8_t slot_id, ipmi_sel_sdr_info_t *info) {
+ int ret;
+ uint8_t rlen = 0;
+
+ ret = bic_ipmb_wrapper(slot_id, NETFN_STORAGE_REQ, CMD_STORAGE_GET_SEL_INFO, NULL, 0, (uint8_t *)info, &rlen);
+
+ return ret;
+}
+
+static int
+_get_sel_rsv(uint8_t slot_id, uint16_t *rsv) {
+ int ret;
+ uint8_t rlen = 0;
+
+ ret = bic_ipmb_wrapper(slot_id, NETFN_STORAGE_REQ, CMD_STORAGE_RSV_SEL, NULL, 0, (uint8_t *) rsv, &rlen);
+ return ret;
+}
+
+int
+bic_get_sel(uint8_t slot_id, ipmi_sel_sdr_req_t *req, ipmi_sel_sdr_res_t *res, uint8_t *rlen) {
+
+ int ret;
+
+ ret = bic_ipmb_wrapper(slot_id, NETFN_STORAGE_REQ, CMD_STORAGE_GET_SEL, (uint8_t *)req, sizeof(ipmi_sel_sdr_req_t), (uint8_t*)res, rlen);
+
+ return ret;
+}
+
+// Read Sensor Data Records (SDR)
+int
+bic_get_sdr_info(uint8_t slot_id, ipmi_sel_sdr_info_t *info) {
+ int ret;
+ uint8_t rlen = 0;
+
+ ret = bic_ipmb_wrapper(slot_id, NETFN_STORAGE_REQ, CMD_STORAGE_GET_SDR_INFO, NULL, 0, (uint8_t *) info, &rlen);
+
+ return ret;
+}
+
+static int
+_get_sdr_rsv(uint8_t slot_id, uint16_t *rsv) {
+ int ret;
+ uint8_t rlen = 0;
+
+ ret = bic_ipmb_wrapper(slot_id, NETFN_STORAGE_REQ, CMD_STORAGE_RSV_SDR, NULL, 0, (uint8_t *) rsv, &rlen);
+
+ return ret;
+}
+
+static int
+_get_sdr(uint8_t slot_id, ipmi_sel_sdr_req_t *req, ipmi_sel_sdr_res_t *res, uint8_t *rlen) {
+ int ret;
+
+ ret = bic_ipmb_wrapper(slot_id, NETFN_STORAGE_REQ, CMD_STORAGE_GET_SDR, (uint8_t *)req, sizeof(ipmi_sel_sdr_req_t), (uint8_t*)res, rlen);
+
+ return ret;
+}
+
+int
+bic_get_sdr(uint8_t slot_id, ipmi_sel_sdr_req_t *req, ipmi_sel_sdr_res_t *res, uint8_t *rlen) {
+ int ret;
+ uint8_t tbuf[MAX_IPMB_RES_LEN] = {0};
+ uint8_t tlen;
+ uint8_t len;
+ ipmi_sel_sdr_res_t *tres;
+ sdr_rec_hdr_t *hdr;
+
+ tres = (ipmi_sel_sdr_res_t *) tbuf;
+
+ // Get SDR reservation ID for the given record
+ ret = _get_sdr_rsv(slot_id, &req->rsv_id);
+ if (ret) {
+ printf("bic_read_sdr: _get_sdr_rsv returns %d\n", ret);
+ return ret;
+ }
+
+ // Initialize the response length to zero
+ *rlen = 0;
+
+ // Read SDR Record Header
+ req->offset = 0;
+ req->nbytes = sizeof(sdr_rec_hdr_t);
+
+ ret = _get_sdr(slot_id, req, tbuf, &tlen);
+ if (ret) {
+ printf("bic_read_sdr: _get_sdr returns %d\n", ret);
+ return ret;
+ }
+
+ // Copy the next record id to response
+ res->next_rec_id = tres->next_rec_id;
+
+ // Copy the header excluding first two bytes(next_rec_id)
+ memcpy(res->data, tres->data, tlen-2);
+
+ // Update response length and offset for next request
+ *rlen += tlen-2;
+ req->offset = tlen-2;
+
+ // Find length of data from header info
+ hdr = (sdr_rec_hdr_t *) tres->data;
+ len = hdr->len;
+
+ // Keep reading chunks of SDR record in a loop
+ while (len > 0) {
+ if (len > SDR_READ_COUNT_MAX) {
+ req->nbytes = SDR_READ_COUNT_MAX;
+ } else {
+ req->nbytes = len;
+ }
+
+ ret = _get_sdr(slot_id, req, tbuf, &tlen);
+ if (ret) {
+ printf("bic_read_sdr: _get_sdr returns %d\n", ret);
+ return ret;
+ }
+
+ // Copy the data excluding the first two bytes(next_rec_id)
+ memcpy(&res->data[req->offset], tres->data, tlen-2);
+
+ // Update response length, offset for next request, and remaining length
+ *rlen += tlen-2;
+ req->offset += tlen-2;
+ len -= tlen-2;
+ }
+
+ return 0;
+}
+
+int
+bic_read_sensor(uint8_t slot_id, uint8_t sensor_num, ipmi_sensor_reading_t *sensor) {
+ int ret;
+ int rlen = 0;
+
+ ret = bic_ipmb_wrapper(slot_id, NETFN_SENSOR_REQ, CMD_SENSOR_GET_SENSOR_READING, (uint8_t *)&sensor_num, 1, (uint8_t *)sensor, &rlen);
+
+ return ret;
+}
OpenPOWER on IntegriCloud