diff options
author | Tian Fang <tfang@fb.com> | 2015-12-14 22:08:40 -0800 |
---|---|---|
committer | Tian Fang <tfang@fb.com> | 2015-12-15 09:49:21 -0800 |
commit | e65a7944211c70f6b5cfb6cedd73cc31105319de (patch) | |
tree | 067082251bc52bc6c09ca87feaa1352d0468a5ac /meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/bic/bic.c | |
parent | 8a67fbdd0e251bb34d55992b0771edba1837d589 (diff) | |
download | ast2050-yocto-openbmc-e65a7944211c70f6b5cfb6cedd73cc31105319de.zip ast2050-yocto-openbmc-e65a7944211c70f6b5cfb6cedd73cc31105319de.tar.gz |
Sync to internal OpenBMC repo f926614
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.c | 349 |
1 files changed, 319 insertions, 30 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 index 55cd56b..4139b44 100644 --- a/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/bic/bic.c +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/bic/bic.c @@ -22,10 +22,15 @@ #include <stdio.h> #include <stdint.h> #include <fcntl.h> +#include <syslog.h> #include "bic.h" #define FRUID_READ_COUNT_MAX 0x30 +#define FRUID_WRITE_COUNT_MAX 0x30 +#define CPLD_WRITE_COUNT_MAX 0x50 #define SDR_READ_COUNT_MAX 0x1A +#define SIZE_SYS_GUID 16 +#define SIZE_IANA_ID 3 enum { IPMB_BUS_SLOT1 = 3, @@ -87,7 +92,9 @@ bic_ipmb_wrapper(uint8_t slot_id, uint8_t netfn, uint8_t cmd, ret = get_ipmb_bus_id(slot_id); if (ret < 0) { - printf("bic_ipmb_wrapper: Wrong Slot ID %d\n", slot_id); +#ifdef DEBUG + syslog(LOG_ERR, "bic_ipmb_wrapper: Wrong Slot ID %d\n", slot_id); +#endif return ret; } @@ -114,8 +121,11 @@ bic_ipmb_wrapper(uint8_t slot_id, uint8_t netfn, uint8_t cmd, // Invoke IPMB library handler lib_ipmb_handle(bus_id, tbuf, tlen, &rbuf, &rlen); + if (rlen == 0) { - printf("bic_ipmb_wrapper: Zero bytes received\n"); +#ifdef DEBUG + syslog(LOG_DEBUG, "bic_ipmb_wrapper: Zero bytes received\n"); +#endif return -1; } @@ -123,7 +133,9 @@ bic_ipmb_wrapper(uint8_t slot_id, uint8_t netfn, uint8_t cmd, res = (ipmb_res_t*) rbuf; if (res->cc) { - printf("bic_ipmb_wrapper: Completion Code: 0x%X\n", res->cc); +#ifdef DEBUG + syslog(LOG_ERR, "bic_ipmb_wrapper: Completion Code: 0x%X\n", res->cc); +#endif return -1; } @@ -148,17 +160,23 @@ bic_get_dev_id(uint8_t slot_id, ipmi_dev_id_t *dev_id) { // Get GPIO value and configuration int bic_get_gpio(uint8_t slot_id, bic_gpio_t *gpio) { + uint8_t tbuf[3] = {0x15, 0xA0, 0x00}; // IANA ID + uint8_t rbuf[7] = {0x00}; 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); + ret = bic_ipmb_wrapper(slot_id, NETFN_OEM_1S_REQ, CMD_OEM_1S_GET_GPIO, tbuf, 0x03, rbuf, &rlen); + + // Ignore first 3 bytes of IANA ID + memcpy((uint8_t*) gpio, &rbuf[3], 4); 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 tbuf[7] = {0x15, 0xA0, 0x00}; // IANA ID + uint8_t rbuf[4] = {0x00}; uint8_t rlen = 0; uint8_t tlen = 0; uint32_t pin; @@ -166,75 +184,245 @@ bic_get_gpio_config(uint8_t slot_id, uint8_t gpio, bic_gpio_config_t *gpio_confi pin = 1 << gpio; - tbuf[0] = pin & 0xFF; - tbuf[1] = (pin >> 8) & 0xFF; - tbuf[2] = (pin >> 16) & 0xFF; - tbuf[3] = (pin >> 24) & 0xFF; + tbuf[3] = pin & 0xFF; + tbuf[4] = (pin >> 8) & 0xFF; + tbuf[5] = (pin >> 16) & 0xFF; + tbuf[6] = (pin >> 24) & 0xFF; - tlen = 4; + tlen = 7; - ret = bic_ipmb_wrapper(slot_id, NETFN_OEM_1S_REQ, CMD_OEM_1S_GET_GPIO_CONFIG, tbuf, tlen, (uint8_t *) gpio_config, &rlen); + ret = bic_ipmb_wrapper(slot_id, NETFN_OEM_1S_REQ, CMD_OEM_1S_GET_GPIO_CONFIG, tbuf, tlen, rbuf, &rlen); + + // Ignore IANA ID + *(uint8_t *) gpio_config = rbuf[3]; 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 tbuf[8] = {0x15, 0xA0, 0x00}; // IANA ID + uint8_t rbuf[4] = {0x00}; 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; + tbuf[3] = pin & 0xFF; + tbuf[4] = (pin >> 8) & 0xFF; + tbuf[5] = (pin >> 16) & 0xFF; + tbuf[6] = (pin >> 24) & 0xFF; + tbuf[7] = (*(uint8_t *) gpio_config) & 0x1F; - tlen = 5; + tlen = 8; ret = bic_ipmb_wrapper(slot_id, NETFN_OEM_1S_REQ, CMD_OEM_1S_SET_GPIO_CONFIG, - tbuf, tlen, &res, &rlen); + tbuf, tlen, rbuf, &rlen); return ret; } // Get BIC Configuration int bic_get_config(uint8_t slot_id, bic_config_t *cfg) { + uint8_t tbuf[3] = {0x15, 0xA0, 0x00}; // IANA ID + uint8_t rbuf[4] = {0x00}; 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); + tbuf, 0x03, rbuf, &rlen); + // Ignore IANA ID + *(uint8_t *) cfg = rbuf[3]; + return ret; } // Set BIC Configuration int bic_set_config(uint8_t slot_id, bic_config_t *cfg) { + uint8_t tbuf[4] = {0x15, 0xA0, 0x00}; // IANA ID uint8_t rlen = 0; uint8_t rbuf[4] = {0}; int ret; + tbuf[3] = *(uint8_t *) cfg; + ret = bic_ipmb_wrapper(slot_id, NETFN_OEM_1S_REQ, CMD_OEM_1S_SET_CONFIG, - (uint8_t *) cfg, 1, rbuf, &rlen); + tbuf, 0x04, rbuf, &rlen); return ret; } // Read POST Buffer int bic_get_post_buf(uint8_t slot_id, uint8_t *buf, uint8_t *len) { + uint8_t tbuf[3] = {0x15, 0xA0, 0x00}; // IANA ID + uint8_t rbuf[255] = {0x00}; + uint8_t rlen = 0; + int ret; + + ret = bic_ipmb_wrapper(slot_id, NETFN_OEM_1S_REQ, CMD_OEM_1S_GET_POST_BUF, tbuf, 0x03, rbuf, &rlen); + + //Ignore IANA ID + memcpy(buf, &rbuf[3], rlen-3); + + *len = rlen - 3; + + return ret; +} + +// Read Firwmare Versions of various components +int +bic_get_fw_ver(uint8_t slot_id, uint8_t comp, uint8_t *ver) { + uint8_t tbuf[4] = {0x15, 0xA0, 0x00}; // IANA ID + uint8_t rbuf[16] = {0x00}; + uint8_t rlen = 0; int ret; - ret = bic_ipmb_wrapper(slot_id, NETFN_OEM_1S_REQ, CMD_OEM_1S_GET_POST_BUF, NULL, 0, buf, len); + // Fill the component for which firmware is requested + tbuf[3] = comp; + + ret = bic_ipmb_wrapper(slot_id, NETFN_OEM_1S_REQ, CMD_OEM_1S_GET_FW_VER, tbuf, 0x04, rbuf, &rlen); + // fw version has to be between 2 and 5 bytes based on component + if (ret || (rlen < 2+SIZE_IANA_ID) || (rlen > 5+SIZE_IANA_ID)) { +#ifdef DEBUG + syslog(LOG_ERR, "bic_get_fw_ver: ret: %d, rlen: %d\n", ret, rlen); +#endif + return -1; + } + + //Ignore IANA ID + memcpy(ver, &rbuf[3], rlen-3); return ret; } +// Update firmware for various components +static int +_update_fw(uint8_t slot_id, uint8_t target, uint32_t offset, uint16_t len, uint8_t *buf) { + uint8_t tbuf[256] = {0x15, 0xA0, 0x00}; // IANA ID + uint8_t rbuf[16] = {0x00}; + uint8_t tlen = 0; + uint8_t rlen = 0; + int ret; + int retries = 3; + + // Fill the component for which firmware is requested + tbuf[3] = target; + + tbuf[4] = (offset) & 0xFF; + tbuf[5] = (offset >> 8) & 0xFF; + tbuf[6] = (offset >> 16) & 0xFF; + tbuf[7] = (offset >> 24) & 0xFF; + + tbuf[8] = len & 0xFF; + tbuf[9] = (len >> 8) & 0xFF; + + memcpy(&tbuf[10], buf, len); + + printf("_update_fw: target: %d, offset: %d, len: %d\n", target, offset, len); + + tlen = len + 10; + +bic_send: + ret = bic_ipmb_wrapper(slot_id, NETFN_OEM_1S_REQ, CMD_OEM_1S_UPDATE_FW, tbuf, tlen, rbuf, &rlen); + if ((ret) && (retries--)) { + sleep(1); + printf("_update_fw: retrying..\n"); + goto bic_send; + } + + return ret; +} + +int +bic_update_fw(uint8_t slot_id, uint8_t comp, char *path) { + int ret; + uint32_t offset; + uint16_t count; + uint8_t buf[256] = {0}; + uint8_t len = 0; + uint8_t target; + int fd; + + // Open the file exclusively for read + fd = open(path, O_RDONLY, 0666); + if (fd < 0) { +#ifdef DEBUG + syslog(LOG_ERR, "bic_update_fw: open fails for path: %s\n", path); +#endif + goto error_exit; + } + + // Write chunks of CPLD binary data in a loop + offset = 0; + while (1) { + // Read from file + count = read(fd, buf, CPLD_WRITE_COUNT_MAX); + if (count <= 0) { + break; + } + + if (count == CPLD_WRITE_COUNT_MAX) { + target = comp; + } else { + target = comp | 0x80; + } + + // Write to the CPLD + ret = _update_fw(slot_id, target, offset, count, buf); + if (ret) { + break; + } + + // Update counter + offset += count; + } + +error_exit: + if (fd > 0 ) { + close(fd); + } + + return ret; +} + +int +bic_me_xmit(uint8_t slot_id, uint8_t *txbuf, uint8_t txlen, uint8_t *rxbuf, uint8_t *rxlen) { + uint8_t tbuf[256] = {0x15, 0xA0, 0x00}; // IANA ID + uint8_t rbuf[256] = {0x00}; + uint8_t rlen = 0; + uint8_t tlen = 0; + int ret; + + // Fill the interface number as ME + tbuf[3] = BIC_INTF_ME; + + // Fill the data to be sent + memcpy(&tbuf[4], txbuf, txlen); + + // Send data length includes IANA ID and interface number + tlen = txlen + 4; + + ret = bic_ipmb_wrapper(slot_id, NETFN_OEM_1S_REQ, CMD_OEM_1S_MSG_OUT, tbuf, tlen, rbuf, &rlen); + if (ret ) { + return -1; + } + + // Make sure the received interface number is same + if (rbuf[3] != tbuf[3]) { + return -1; + } + + // Copy the received data to caller skipping header + memcpy(rxbuf, &rbuf[7], rlen-7); + + *rxlen = rlen-7; + + return 0; +} + // Read 1S server's FRUID int bic_get_fruid_info(uint8_t slot_id, uint8_t fru_id, ipmi_fruid_info_t *info) { @@ -279,19 +467,23 @@ bic_read_fruid(uint8_t slot_id, uint8_t fru_id, const char *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); +#ifdef DEBUG + syslog(LOG_ERR, "bic_read_fruid: open fails for path: %s\n", path); +#endif 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); +#ifdef DEBUG + syslog(LOG_ERR, "bic_read_fruid: bic_read_fruid_info returns %d\n", ret); +#endif goto error_exit; } // Indicates the size of the FRUID - nread = (info.size_msb << 8) + (info.size_lsb); + nread = (info.size_msb << 6) + (info.size_lsb); // Read chunks of FRUID binary data in a loop offset = 0; @@ -304,7 +496,9 @@ bic_read_fruid(uint8_t slot_id, uint8_t fru_id, const char *path) { ret = _read_fruid(slot_id, fru_id, offset, count, rbuf, &rlen); if (ret) { - printf("bic_read_fruid: ipmb_wrapper fails\n"); +#ifdef DEBUG + syslog(LOG_ERR, "bic_read_fruid: ipmb_wrapper fails\n"); +#endif goto error_exit; } @@ -324,6 +518,79 @@ error_exit: return ret; } +static int +_write_fruid(uint8_t slot_id, uint8_t fru_id, uint32_t offset, uint8_t count, uint8_t *buf) { + int ret; + uint8_t tbuf[64] = {0}; + uint8_t rbuf[4] = {0}; + uint8_t tlen = 0; + uint8_t rlen = 0; + + tbuf[0] = fru_id; + tbuf[1] = offset & 0xFF; + tbuf[2] = (offset >> 8) & 0xFF; + + memcpy(&tbuf[3], buf, count); + tlen = count + 3; + + ret = bic_ipmb_wrapper(slot_id, NETFN_STORAGE_REQ, CMD_STORAGE_WRITE_FRUID_DATA, tbuf, tlen, rbuf, &rlen); + + if (ret) { + return ret; + } + + if (rbuf[0] != count) { + return -1; + } + + return ret; +} + +int +bic_write_fruid(uint8_t slot_id, uint8_t fru_id, const char *path) { + int ret; + uint32_t offset; + uint8_t count; + uint8_t buf[64] = {0}; + uint8_t len = 0; + int fd; + + // Open the file exclusively for read + fd = open(path, O_RDONLY, 0666); + if (fd < 0) { +#ifdef DEBUG + syslog(LOG_ERR, "bic_write_fruid: open fails for path: %s\n", path); +#endif + goto error_exit; + } + + // Write chunks of FRUID binary data in a loop + offset = 0; + while (1) { + // Read from file + count = read(fd, buf, FRUID_WRITE_COUNT_MAX); + if (count <= 0) { + break; + } + + // Write to the FRUID + ret = _write_fruid(slot_id, fru_id, offset, count, buf); + if (ret) { + break; + } + + // Update counter + offset += count; + } + +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) { @@ -398,7 +665,9 @@ bic_get_sdr(uint8_t slot_id, ipmi_sel_sdr_req_t *req, ipmi_sel_sdr_res_t *res, u // 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); +#ifdef DEBUG + syslog(LOG_ERR, "bic_read_sdr: _get_sdr_rsv returns %d\n", ret); +#endif return ret; } @@ -411,7 +680,9 @@ bic_get_sdr(uint8_t slot_id, ipmi_sel_sdr_req_t *req, ipmi_sel_sdr_res_t *res, u ret = _get_sdr(slot_id, req, tbuf, &tlen); if (ret) { - printf("bic_read_sdr: _get_sdr returns %d\n", ret); +#ifdef DEBUG + syslog(LOG_ERR, "bic_read_sdr: _get_sdr returns %d\n", ret); +#endif return ret; } @@ -439,7 +710,9 @@ bic_get_sdr(uint8_t slot_id, ipmi_sel_sdr_req_t *req, ipmi_sel_sdr_res_t *res, u ret = _get_sdr(slot_id, req, tbuf, &tlen); if (ret) { - printf("bic_read_sdr: _get_sdr returns %d\n", ret); +#ifdef DEBUG + syslog(LOG_ERR, "bic_read_sdr: _get_sdr returns %d\n", ret); +#endif return ret; } @@ -464,3 +737,19 @@ bic_read_sensor(uint8_t slot_id, uint8_t sensor_num, ipmi_sensor_reading_t *sens return ret; } + +int +bic_get_sys_guid(uint8_t slot_id, uint8_t *guid) { + int ret; + int rlen = 0; + + ret = bic_ipmb_wrapper(slot_id, NETFN_APP_REQ, CMD_APP_GET_SYSTEM_GUID, NULL, 0, guid, &rlen); + if (rlen != SIZE_SYS_GUID) { +#ifdef DEBUG + syslog(LOG_ERR, "bic_get_sys_guid: returned rlen of %d\n"); +#endif + return -1; + } + + return ret; +} |