meta-facebook/meta-clearcreek/recipes-fbcc/plat-libs/files/pal/pal.c (986 lines of code) (raw):
/*
*
* 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 <syslog.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
#include <sys/time.h>
#include <openbmc/libgpio.h>
#include <openbmc/obmc-i2c.h>
#include "pal.h"
#define MB_BIN "/tmp/fruid_mb.bin"
#define MB_EEPROM "/sys/class/i2c-dev/i2c-6/device/6-0054/eeprom"
#define PDB_BIN "/tmp/fruid_pdb.bin"
#define PDB_EEPROM "/sys/class/i2c-dev/i2c-5/device/5-0054/eeprom"
#define BSM_BIN "/tmp/fruid_bsm.bin"
#define BSM_EEPROM "/sys/class/i2c-dev/i2c-23/device/23-0056/eeprom"
#define AVA1_BIN "/tmp/fruid_ava1.bin"
#define AVA1_EEPROM "/sys/class/i2c-dev/i2c-21/device/21-0050/eeprom"
#define AVA2_BIN "/tmp/fruid_ava2.bin"
#define AVA2_EEPROM "/sys/class/i2c-dev/i2c-22/device/22-0050/eeprom"
#define E1S1_BIN "/tmp/fruid_e1s1.bin"
#define E1S1_EEPROM "/sys/class/i2c-dev/i2c-21/device/21-0050/eeprom"
#define E1S2_BIN "/tmp/fruid_e1s2.bin"
#define E1S2_EEPROM "/sys/class/i2c-dev/i2c-22/device/22-0050/eeprom"
#define FIO_EEPROM "/sys/class/i2c-dev/i2c-8/device/8-0051/eeprom"
#define FIO_BIN "/tmp/fruid_fio.bin"
#define NIC0_EEPROM "/sys/class/i2c-dev/i2c-1/device/1-0050/eeprom"
#define NIC0_BIN "/tmp/fruid_nic0.bin"
#define NIC1_EEPROM "/sys/class/i2c-dev/i2c-9/device/9-0050/eeprom"
#define NIC1_BIN "/tmp/fruid_nic1.bin"
#define NIC2_EEPROM "/sys/class/i2c-dev/i2c-2/device/2-0050/eeprom"
#define NIC2_BIN "/tmp/fruid_nic2.bin"
#define NIC3_EEPROM "/sys/class/i2c-dev/i2c-10/device/10-0050/eeprom"
#define NIC3_BIN "/tmp/fruid_nic3.bin"
#define NIC4_EEPROM "/sys/class/i2c-dev/i2c-4/device/4-0050/eeprom"
#define NIC4_BIN "/tmp/fruid_nic4.bin"
#define NIC5_EEPROM "/sys/class/i2c-dev/i2c-11/device/11-0050/eeprom"
#define NIC5_BIN "/tmp/fruid_nic5.bin"
#define NIC6_EEPROM "/sys/class/i2c-dev/i2c-7/device/7-0050/eeprom"
#define NIC6_BIN "/tmp/fruid_nic6.bin"
#define NIC7_EEPROM "/sys/class/i2c-dev/i2c-13/device/13-0050/eeprom"
#define NIC7_BIN "/tmp/fruid_nic7.bin"
#define BMC_IPMB_SLAVE_ADDR 0x17
#define OFFSET_DEV_GUID 0x1800
#define LAST_KEY "last_key"
#define MAX_RETRY 3
const char pal_fru_list[] = "all, mb, bsm, pdb, carrier1, carrier2, fio, nic0, nic1, nic2, nic3, nic4, nic5, nic6, nic7";
const char pal_server_list[] = "";
struct pal_key_cfg {
char *name;
char *def_val;
int (*function)(int, void*);
} key_cfg[] = {
/* name, default value, function */
{"identify_sled", "off", NULL},
{"timestamp_sled", "0", NULL},
{KEY_MB_SNR_HEALTH, "1", NULL},
{KEY_MB_SEL_ERROR, "1", NULL},
{KEY_PDB_SNR_HEALTH, "1", NULL},
{KEY_CARRIER1_SNR_HEALTH, "1", NULL},
{KEY_CARRIER2_SNR_HEALTH, "1", NULL},
{KEY_NIC0_SNR_HEALTH, "1", NULL},
{KEY_NIC1_SNR_HEALTH, "1", NULL},
{KEY_NIC2_SNR_HEALTH, "1", NULL},
{KEY_NIC3_SNR_HEALTH, "1", NULL},
{KEY_NIC4_SNR_HEALTH, "1", NULL},
{KEY_NIC5_SNR_HEALTH, "1", NULL},
{KEY_NIC6_SNR_HEALTH, "1", NULL},
{KEY_NIC7_SNR_HEALTH, "1", NULL},
{"ntp_server", "", NULL},
/* Add more Keys here */
{LAST_KEY, LAST_KEY, NULL} /* This is the last key of the list */
};
enum key_event {
KEY_BEFORE_SET,
KEY_AFTER_INI,
};
char g_dev_guid[GUID_SIZE] = {0};
int pal_check_carrier_type(int index)
{
char type[64] = {0};
if(index == 0) {
if(kv_get("carrier_0", type, NULL, 0) < 0) {
syslog(LOG_WARNING, "%s: not find carrier type", __func__);
}
} else if (index == 1) {
if(kv_get("carrier_1", type, NULL, 0) < 0) {
syslog(LOG_WARNING, "%s: not find carrier type", __func__);
}
}
if (!strcmp(type, "m.2") || !strcmp(type, "m.2_v2")) {
return M2;
} else if (!strcmp(type, "e1.s") || !strcmp(type, "e1.s_v2")) {
return E1S;
}
return 0;
}
int pal_get_fru_id(char *str, uint8_t *fru)
{
if (!strcmp(str, "all")) {
*fru = FRU_ALL;
} else if (!strcmp(str, "mb")) {
*fru = FRU_MB;
} else if (!strcmp(str, "bsm")) {
*fru = FRU_BSM;
} else if (!strcmp(str, "pdb")) {
*fru = FRU_PDB;
} else if (!strcmp(str, "carrier1")) {
*fru = FRU_CARRIER1;
} else if (!strcmp(str, "carrier2")) {
*fru = FRU_CARRIER2;
} else if (!strcmp(str, "fio")) {
*fru = FRU_FIO;
} else if (!strcmp(str, "nic0")) {
*fru = FRU_NIC0;
} else if (!strcmp(str, "nic1")) {
*fru = FRU_NIC1;
} else if (!strcmp(str, "nic2")) {
*fru = FRU_NIC2;
} else if (!strcmp(str, "nic3")) {
*fru = FRU_NIC3;
} else if (!strcmp(str, "nic4")) {
*fru = FRU_NIC4;
} else if (!strcmp(str, "nic5")) {
*fru = FRU_NIC5;
} else if (!strcmp(str, "nic6")) {
*fru = FRU_NIC6;
} else if (!strcmp(str, "nic7")) {
*fru = FRU_NIC7;
} else if ( !strcmp(str, "nic") || !strcmp(str, "vr") ||
!strcmp(str, "bmc") || !strcmp(str, "ocpdbg")) {
return -1;
} else {
syslog(LOG_WARNING, "%s: Wrong fru name %s", __func__, str);
return -1;
}
return 0;
}
int pal_get_fruid_name(uint8_t fru, char *name)
{
if (fru == FRU_MB)
sprintf(name, "Base Board");
else if (fru == FRU_BSM)
sprintf(name, "BSM");
else if (fru == FRU_PDB)
sprintf(name, "PDB");
else if (fru == FRU_CARRIER1) {
if( pal_check_carrier_type(0) == M2 )
sprintf(name, "M2 Carrier1");
else
sprintf(name, "E1.s Carrier1");
}
else if (fru == FRU_CARRIER2) {
if( pal_check_carrier_type(1) == M2 )
sprintf(name, "M2 Carrier2");
else
sprintf(name, "E1.s Carrier2");
}
else if (fru == FRU_FIO)
sprintf(name, "Front IO");
else if (fru == FRU_NIC0)
sprintf(name, "NIC 0");
else if (fru == FRU_NIC1)
sprintf(name, "NIC 1");
else if (fru == FRU_NIC2)
sprintf(name, "NIC 2");
else if (fru == FRU_NIC3)
sprintf(name, "NIC 3");
else if (fru == FRU_NIC4)
sprintf(name, "NIC 4");
else if (fru == FRU_NIC5)
sprintf(name, "NIC 5");
else if (fru == FRU_NIC6)
sprintf(name, "NIC 6");
else if (fru == FRU_NIC7)
sprintf(name, "NIC 7");
else
return -1;
return 0;
}
int pal_is_fru_prsnt(uint8_t fru, uint8_t *status)
{
int ret = -1;
gpio_desc_t *desc = NULL;
gpio_value_t value;
switch (fru) {
case FRU_MB:
case FRU_PDB:
case FRU_BSM:
case FRU_CARRIER1:
case FRU_CARRIER2:
case FRU_FIO:
*status = 1;
return 0;
case FRU_NIC0:
desc = gpio_open_by_shadow("OCP_V3_0_PRSNTB_R_N");
break;
case FRU_NIC1:
desc = gpio_open_by_shadow("OCP_V3_4_PRSNTB_R_N");
break;
case FRU_NIC2:
desc = gpio_open_by_shadow("OCP_V3_1_PRSNTB_R_N");
break;
case FRU_NIC3:
desc = gpio_open_by_shadow("OCP_V3_5_PRSNTB_R_N");
break;
case FRU_NIC4:
desc = gpio_open_by_shadow("OCP_V3_2_PRSNTB_R_N");
break;
case FRU_NIC5:
desc = gpio_open_by_shadow("OCP_V3_6_PRSNTB_R_N");
break;
case FRU_NIC6:
desc = gpio_open_by_shadow("OCP_V3_3_PRSNTB_R_N");
break;
case FRU_NIC7:
desc = gpio_open_by_shadow("OCP_V3_7_PRSNTB_R_N");
break;
default:
return -1;
}
if (desc == NULL)
return -1;
if (gpio_get_value(desc, &value) == 0) {
*status = !value;
ret = 0;
}
gpio_close(desc);
return ret;
}
int pal_is_fru_ready(uint8_t fru, uint8_t *status)
{
*status = 1;
return 0;
}
int pal_get_fru_name(uint8_t fru, char *name)
{
if (fru == FRU_MB) {
strcpy(name, "mb");
} else if (fru == FRU_BSM) {
strcpy(name, "bsm");
} else if (fru == FRU_PDB) {
strcpy(name, "pdb");
} else if (fru == FRU_NIC0) {
strcpy(name, "nic0");
} else if (fru == FRU_NIC1) {
strcpy(name, "nic1");
} else if (fru == FRU_NIC2) {
strcpy(name, "nic2");
} else if (fru == FRU_NIC3) {
strcpy(name, "nic3");
} else if (fru == FRU_NIC4) {
strcpy(name, "nic4");
} else if (fru == FRU_NIC5) {
strcpy(name, "nic5");
} else if (fru == FRU_NIC6) {
strcpy(name, "nic6");
} else if (fru == FRU_NIC7) {
strcpy(name, "nic7");
} else if (fru == FRU_CARRIER1) {
strcpy(name, "carrier1");
} else if (fru == FRU_CARRIER2) {
strcpy(name, "carrier2");
} else if (fru == FRU_FIO) {
strcpy(name, "fio");
} else {
if (fru > MAX_NUM_FRUS)
return -1;
syslog(LOG_WARNING, "%s: Wrong fruid %d", __func__, fru);
return -1;
}
return 0;
}
int pal_get_fruid_path(uint8_t fru, char *path)
{
if (fru == FRU_MB)
sprintf(path, MB_BIN);
else if (fru == FRU_PDB)
sprintf(path, PDB_BIN);
else if (fru == FRU_BSM)
sprintf(path, BSM_BIN);
else if (fru == FRU_CARRIER1) {
if( pal_check_carrier_type(0) == M2 )
sprintf(path, AVA1_BIN);
else
sprintf(path, E1S1_BIN);
}
else if (fru == FRU_CARRIER2) {
if( pal_check_carrier_type(1) == M2 )
sprintf(path, AVA2_BIN);
else
sprintf(path, E1S2_BIN);
}
else if (fru == FRU_FIO)
sprintf(path, FIO_BIN);
else if (fru == FRU_NIC0)
sprintf(path, NIC0_BIN);
else if (fru == FRU_NIC1)
sprintf(path, NIC1_BIN);
else if (fru == FRU_NIC2)
sprintf(path, NIC2_BIN);
else if (fru == FRU_NIC3)
sprintf(path, NIC3_BIN);
else if (fru == FRU_NIC4)
sprintf(path, NIC4_BIN);
else if (fru == FRU_NIC5)
sprintf(path, NIC5_BIN);
else if (fru == FRU_NIC6)
sprintf(path, NIC6_BIN);
else if (fru == FRU_NIC7)
sprintf(path, NIC7_BIN);
else
return -1;
return 0;
}
void pal_get_eth_intf_name(char* intf_name)
{
snprintf(intf_name, 8, "usb0");
}
int pal_get_fruid_eeprom_path(uint8_t fru, char *path)
{
if (fru == FRU_MB)
sprintf(path, MB_EEPROM);
else if (fru == FRU_PDB)
sprintf(path, PDB_EEPROM);
else if (fru == FRU_BSM)
sprintf(path, BSM_EEPROM);
else if (fru == FRU_CARRIER1) {
if( pal_check_carrier_type(0) == M2 )
sprintf(path, AVA1_EEPROM);
else
sprintf(path, E1S1_EEPROM);
}
else if (fru == FRU_CARRIER2) {
if( pal_check_carrier_type(1) == M2 )
sprintf(path, AVA2_EEPROM);
else
sprintf(path, E1S2_EEPROM);
}
else if (fru == FRU_FIO)
sprintf(path, FIO_EEPROM);
else if (fru == FRU_NIC0)
sprintf(path, NIC0_EEPROM);
else if (fru == FRU_NIC1)
sprintf(path, NIC1_EEPROM);
else if (fru == FRU_NIC2)
sprintf(path, NIC2_EEPROM);
else if (fru == FRU_NIC3)
sprintf(path, NIC3_EEPROM);
else if (fru == FRU_NIC4)
sprintf(path, NIC4_EEPROM);
else if (fru == FRU_NIC5)
sprintf(path, NIC5_EEPROM);
else if (fru == FRU_NIC6)
sprintf(path, NIC6_EEPROM);
else if (fru == FRU_NIC7)
sprintf(path, NIC7_EEPROM);
else
return -1;
return 0;
}
int pal_get_fru_list(char *list)
{
strcpy(list, pal_fru_list);
return 0;
}
int pal_get_fru_capability(uint8_t fru, unsigned int *caps)
{
int ret = 0;
switch(fru) {
case FRU_MB:
*caps = FRU_CAPABILITY_FRUID_ALL | FRU_CAPABILITY_SENSOR_ALL |
FRU_CAPABILITY_POWER_STATUS | FRU_CAPABILITY_POWER_ON | FRU_CAPABILITY_POWER_OFF | FRU_CAPABILITY_POWER_CYCLE;
break;
case FRU_BSM:
*caps = FRU_CAPABILITY_FRUID_ALL | FRU_CAPABILITY_SENSOR_ALL | FRU_CAPABILITY_MANAGEMENT_CONTROLLER;
break;
case FRU_PDB:
case FRU_CARRIER1:
case FRU_CARRIER2:
case FRU_FIO:
*caps = FRU_CAPABILITY_FRUID_ALL | FRU_CAPABILITY_SENSOR_ALL;
break;
case FRU_NIC0:
case FRU_NIC1:
case FRU_NIC2:
case FRU_NIC3:
case FRU_NIC4:
case FRU_NIC5:
case FRU_NIC6:
case FRU_NIC7:
*caps = FRU_CAPABILITY_SENSOR_ALL | FRU_CAPABILITY_NETWORK_CARD;
break;
default:
ret = -1;
break;
}
return ret;
}
int pal_get_bmc_ipmb_slave_addr(uint16_t *slave_addr, uint8_t bus_id)
{
if (bus_id == 0) {
*slave_addr = BMC_IPMB_SLAVE_ADDR;
} else {
*slave_addr = 0x10;
}
return 0;
}
int pal_set_usb_path(uint8_t slot, uint8_t endpoint)
{
int ret = CC_SUCCESS;
char gpio_name[16] = {0};
gpio_desc_t *desc;
gpio_value_t value;
if (slot > SERVER_2 || endpoint > PCH) {
ret = CC_PARAM_OUT_OF_RANGE;
goto exit;
}
strcpy(gpio_name ,"USB2_SEL0");
desc = gpio_open_by_shadow(gpio_name);
if (!desc) {
ret = CC_UNSPECIFIED_ERROR;
goto exit;
}
value = endpoint == PCH? GPIO_VALUE_HIGH: GPIO_VALUE_LOW;
if (gpio_set_value(desc, value)) {
ret = CC_UNSPECIFIED_ERROR;
goto bail;
}
gpio_close(desc);
strcpy(gpio_name ,"USB2_SEL1");
desc = gpio_open_by_shadow(gpio_name);
if (!desc) {
ret = CC_UNSPECIFIED_ERROR;
goto exit;
}
value = slot%2 == 0? GPIO_VALUE_HIGH: GPIO_VALUE_LOW;
if (gpio_set_value(desc, value)) {
ret = CC_UNSPECIFIED_ERROR;
goto bail;
}
bail:
gpio_close(desc);
exit:
return ret;
}
static int pal_key_index(char *key)
{
int i = 0;
while (strcmp(key_cfg[i].name, LAST_KEY)) {
// If Key is valid, return success
if (!strcmp(key, key_cfg[i].name))
return i;
i++;
}
#ifdef DEBUG
syslog(LOG_WARNING, "pal_key_index: invalid key - %s", key);
#endif
return -1;
}
int pal_get_key_value(char *key, char *value)
{
int index;
// Check is key is defined and valid
if ((index = pal_key_index(key)) < 0)
return -1;
return kv_get(key, value, NULL, KV_FPERSIST);
}
int pal_set_key_value(char *key, char *value)
{
int index, ret;
// Check is key is defined and valid
if ((index = pal_key_index(key)) < 0)
return -1;
if (key_cfg[index].function) {
ret = key_cfg[index].function(KEY_BEFORE_SET, value);
if (ret < 0)
return ret;
}
return kv_set(key, value, 0, KV_FPERSIST);
}
int
pal_is_bmc_por(void) {
char por[MAX_VALUE_LEN] = {0};
int rc;
rc = kv_get("ast_por", por, NULL, 0);
if (rc < 0) {
syslog(LOG_DEBUG, "%s(): kv_get for ast_por failed", __func__);
return -1;
}
if (!strcmp(por, "1"))
return 1;
else if (!strcmp(por, "0"))
return 0;
else {
syslog(LOG_WARNING, "%s(): Cannot find corresponding ast_por", __func__);
return -1;
}
return 0;
}
int pal_set_id_led(uint8_t status)
{
int ret;
int fd;
char fn[32] = "/dev/i2c-8";
uint8_t tbuf[16] = {0};
uint8_t rbuf[16] = {0};
uint8_t addr = 0xEE;
int retry_count = 0;
fd = open(fn, O_RDWR);
if(fd < 0) {
syslog(LOG_WARNING,"[%s]Cannot open i2c bus", __func__);
ret = PAL_ENOTSUP;
goto error_exit;
}
do {
tbuf[0] = 0x03;
ret = i2c_rdwr_msg_transfer(fd, addr, tbuf, 1, rbuf, 1);
if(ret < 0) {
syslog(LOG_WARNING,"[%s] Cannot read i2c", __func__);
retry_count++;
msleep(200);
if(retry_count >= MAX_RETRY)
goto error_exit;
}
} while(retry_count <= MAX_RETRY && ret < 0);
retry_count = 0;
do {
tbuf[0] = 0x03;
if(status)
tbuf[1] = rbuf[0] | 0x40;
else
tbuf[1] = rbuf[0] & 0xBF;
ret = i2c_rdwr_msg_transfer(fd, addr, tbuf, 2, rbuf, 0);
if(ret < 0) {
syslog(LOG_WARNING,"[%s] Cannot write i2c", __func__);
retry_count++;
msleep(200);
if(retry_count >= MAX_RETRY)
goto error_exit;
}
} while(retry_count <= MAX_RETRY && ret < 0);
error_exit:
if (fd > 0){
close(fd);
}
return ret;
}
int pal_set_def_key_value()
{
int i;
char key[MAX_KEY_LEN] = {0};
for (i = 0; strcmp(key_cfg[i].name, LAST_KEY) != 0; i++) {
if (kv_set(key_cfg[i].name, key_cfg[i].def_val, 0, KV_FCREATE | KV_FPERSIST)) {
#ifdef DEBUG
syslog(LOG_WARNING, "pal_set_def_key_value: kv_set failed.");
#endif
}
if (key_cfg[i].function) {
key_cfg[i].function(KEY_AFTER_INI, key_cfg[i].name);
}
}
/* Actions to be taken on Power On Reset */
if (pal_is_bmc_por()) {
/* Clear all the SEL errors */
/* Write the value "1" which means FRU_STATUS_GOOD */
memset(key, 0, MAX_KEY_LEN);
strcpy(key, KEY_MB_SEL_ERROR);
pal_set_key_value(key, "1");
/* Clear all the sensor health files*/
/* Write the value "1" which means FRU_STATUS_GOOD */
memset(key, 0, MAX_KEY_LEN);
strcpy(key, KEY_MB_SNR_HEALTH);
pal_set_key_value(key, "1");
memset(key, 0, MAX_KEY_LEN);
strcpy(key, KEY_PDB_SNR_HEALTH);
pal_set_key_value(key, "1");
memset(key, 0, MAX_KEY_LEN);
strcpy(key, KEY_CARRIER1_SNR_HEALTH);
pal_set_key_value(key, "1");
memset(key, 0, MAX_KEY_LEN);
strcpy(key, KEY_CARRIER2_SNR_HEALTH);
pal_set_key_value(key, "1");
memset(key, 0, MAX_KEY_LEN);
strcpy(key, KEY_NIC0_SNR_HEALTH);
pal_set_key_value(key, "1");
memset(key, 0, MAX_KEY_LEN);
strcpy(key, KEY_NIC1_SNR_HEALTH);
pal_set_key_value(key, "1");
memset(key, 0, MAX_KEY_LEN);
strcpy(key, KEY_NIC2_SNR_HEALTH);
pal_set_key_value(key, "1");
memset(key, 0, MAX_KEY_LEN);
strcpy(key, KEY_NIC3_SNR_HEALTH);
pal_set_key_value(key, "1");
memset(key, 0, MAX_KEY_LEN);
strcpy(key, KEY_NIC4_SNR_HEALTH);
pal_set_key_value(key, "1");
memset(key, 0, MAX_KEY_LEN);
strcpy(key, KEY_NIC5_SNR_HEALTH);
pal_set_key_value(key, "1");
memset(key, 0, MAX_KEY_LEN);
strcpy(key, KEY_NIC6_SNR_HEALTH);
pal_set_key_value(key, "1");
memset(key, 0, MAX_KEY_LEN);
strcpy(key, KEY_NIC7_SNR_HEALTH);
pal_set_key_value(key, "1");
}
return 0;
}
int pal_get_sysfw_ver(uint8_t fru, uint8_t *ver)
{
// No BIOS
return -1;
}
void pal_get_chassis_status(uint8_t fru, uint8_t *req_data, uint8_t *res_data, uint8_t *res_len)
{
int policy = POWER_CFG_ON; // Always On
unsigned char *data = res_data;
*data++ = ((pal_is_server_off())?0x00:0x01) | (policy << 5);
*data++ = 0x00; // Last Power Event
*data++ = 0x40; // Misc. Chassis Status
*data++ = 0x00; // Front Panel Button Disable
*res_len = data - res_data;
}
void pal_dump_key_value(void)
{
int ret;
int i = 0;
char value[MAX_VALUE_LEN] = {0x0};
while (strcmp(key_cfg[i].name, LAST_KEY)) {
printf("%s:", key_cfg[i].name);
if ((ret = kv_get(key_cfg[i].name, value, NULL, KV_FPERSIST)) < 0) {
printf("\n");
} else {
printf("%s\n", value);
}
i++;
memset(value, 0, MAX_VALUE_LEN);
}
}
int pal_slotid_to_fruid(int slotid)
{
// FRU ID remapping, we start from FRU_MB = 1
return slotid + 1;
}
int pal_get_platform_id(uint8_t *id)
{
static bool cached = false;
static unsigned int cached_id = 0;
if (!cached) {
const char *shadows[] = {
"BOARD_ID0",
"BOARD_ID1",
"BOARD_ID2"
};
if (gpio_get_value_by_shadow_list(shadows, ARRAY_SIZE(shadows), &cached_id)) {
return -1;
}
cached = true;
}
*id = (uint8_t)cached_id;
return 0;
}
int
pal_get_board_rev_id(uint8_t *id) {
char key[MAX_KEY_LEN];
char value[MAX_VALUE_LEN] = {0};
sprintf(key, "mb_rev");
if (kv_get(key, value, NULL, 0)) {
return false;
}
*id = atoi(value);
return 0;
}
int
pal_get_board_id(uint8_t slot, uint8_t *req_data, uint8_t req_len, uint8_t *res_data, uint8_t *res_len) {
int ret;
uint8_t platform_id = 0x00;
uint8_t board_rev_id = 0x00;
int completion_code=CC_UNSPECIFIED_ERROR;
ret = pal_get_platform_id(&platform_id);
if (ret) {
*res_len = 0x00;
return completion_code;
}
ret = pal_get_board_rev_id(&board_rev_id);
if (ret) {
*res_len = 0x00;
return completion_code;
}
// Prepare response buffer
completion_code = CC_SUCCESS;
res_data[0] = platform_id;
res_data[1] = board_rev_id;
*res_len = 0x02;
return completion_code;
}
int pal_devnum_to_fruid(int devnum)
{
// 1 = server, 2 = BMC ifself
return devnum == 0? 2: devnum;
}
int
pal_control_mux_to_target_ch(uint8_t channel, uint8_t bus, uint8_t mux_addr)
{
int ret;
int fd;
char fn[32];
uint8_t retry;
uint8_t tbuf[16] = {0};
uint8_t rbuf[16] = {0};
snprintf(fn, sizeof(fn), "/dev/i2c-%d", bus);
fd = open(fn, O_RDWR);
if(fd < 0) {
syslog(LOG_WARNING,"[%s]Cannot open bus %d", __func__, bus);
ret = PAL_ENOTSUP;
goto error_exit;
}
tbuf[0] = channel;
retry = MAX_READ_RETRY;
while(retry > 0) {
ret = i2c_rdwr_msg_transfer(fd, mux_addr, tbuf, 1, rbuf, 0);
if (PAL_EOK == ret){
break;
}
msleep(50);
retry--;
}
if(ret < 0) {
syslog(LOG_WARNING,"[%s] Cannot switch the mux on bus %d", __func__, bus);
goto error_exit;
}
error_exit:
if (fd > 0){
close(fd);
}
return ret;
}
// GUID for System and Device
static int pal_get_guid(uint16_t offset, char *guid) {
int fd = 0;
ssize_t bytes_rd;
errno = 0;
// Check if file is present
if (access(MB_EEPROM, F_OK) == -1) {
syslog(LOG_ERR, "pal_get_guid: unable to access the %s file: %s",
MB_EEPROM, strerror(errno));
return errno;
}
// Open the file
fd = open(MB_EEPROM, O_RDONLY);
if (fd == -1) {
syslog(LOG_ERR, "pal_get_guid: unable to open the %s file: %s",
MB_EEPROM, strerror(errno));
return errno;
}
// seek to the offset
lseek(fd, offset, SEEK_SET);
// Read bytes from location
bytes_rd = read(fd, guid, GUID_SIZE);
if (bytes_rd != GUID_SIZE) {
syslog(LOG_ERR, "pal_get_guid: read to %s file failed: %s",
MB_EEPROM, strerror(errno));
goto err_exit;
}
err_exit:
close(fd);
return errno;
}
static int pal_set_guid(uint16_t offset, char *guid) {
int fd = 0;
ssize_t bytes_wr;
errno = 0;
// Check for file presence
if (access(MB_EEPROM, F_OK) == -1) {
syslog(LOG_ERR, "pal_set_guid: unable to access the %s file: %s",
MB_EEPROM, strerror(errno));
return errno;
}
// Open file
fd = open(MB_EEPROM, O_WRONLY);
if (fd == -1) {
syslog(LOG_ERR, "pal_set_guid: unable to open the %s file: %s",
MB_EEPROM, strerror(errno));
return errno;
}
// Seek the offset
lseek(fd, offset, SEEK_SET);
// Write GUID data
bytes_wr = write(fd, guid, GUID_SIZE);
if (bytes_wr != GUID_SIZE) {
syslog(LOG_ERR, "pal_set_guid: write to %s file failed: %s",
MB_EEPROM, strerror(errno));
goto err_exit;
}
err_exit:
close(fd);
return errno;
}
int pal_set_dev_guid(uint8_t fru, char *str) {
pal_populate_guid(g_dev_guid, str);
return pal_set_guid(OFFSET_DEV_GUID, g_dev_guid);
}
void pal_update_ts_sled()
{
char key[MAX_KEY_LEN] = {0};
char tstr[MAX_VALUE_LEN] = {0};
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
sprintf(tstr, "%ld", ts.tv_sec);
sprintf(key, "timestamp_sled");
pal_set_key_value(key, tstr);
}
int pal_set_carrier_board_mux(uint8_t bus) {
int ret;
int fd;
char fn[32];
uint8_t retry;
uint8_t tbuf[16] = {0};
uint8_t rbuf[16] = {0};
uint8_t mux_addr = 0xE6;
snprintf(fn, sizeof(fn), "/dev/i2c-%d", bus);
fd = open(fn, O_RDWR);
if(fd < 0) {
syslog(LOG_WARNING,"[%s]Cannot open bus %d", __func__, bus);
ret = PAL_ENOTSUP;
goto error_exit;
}
tbuf[0] = 0x80;
retry = MAX_READ_RETRY;
while(retry > 0) {
ret = i2c_rdwr_msg_transfer(fd, mux_addr, tbuf, 1, rbuf, 0);
if (PAL_EOK == ret) {
break;
}
msleep(50);
retry--;
}
if(ret < 0) {
syslog(LOG_WARNING,"[%s] Cannot set carrier board mux on bus %d", __func__, bus);
goto error_exit;
}
error_exit:
if (fd > 0) {
close(fd);
}
return ret;
}
int pal_set_ioexp_direction(uint8_t bus, char* dirction) {
int ret;
int fd;
char fn[32];
uint8_t retry;
uint8_t tbuf[16] = {0};
uint8_t rbuf[16] = {0};
uint8_t ioexp_addr = 0xE8;
uint8_t cmds[2] = {0x03, 0x07};
snprintf(fn, sizeof(fn), "/dev/i2c-%d", bus);
fd = open(fn, O_RDWR);
if(fd < 0) {
syslog(LOG_WARNING,"[%s]Cannot open bus %d", __func__, bus);
ret = PAL_ENOTSUP;
goto error_exit;
}
for (int i = 0; i < sizeof(cmds); i++) {
tbuf[0] = cmds[i];
if(!strcmp(dirction, "out")) {
tbuf[1] = 0x00;
} else {
tbuf[1] = 0xff;
}
retry = MAX_READ_RETRY;
while(retry > 0) {
ret = i2c_rdwr_msg_transfer(fd, ioexp_addr, tbuf, 2, rbuf, 0);
if (PAL_EOK == ret) {
break;
}
msleep(50);
retry--;
}
}
if(ret < 0) {
syslog(LOG_WARNING,"[%s] Cannot set ioexp direction on bus %d", __func__, bus);
goto error_exit;
}
error_exit:
if (fd > 0) {
close(fd);
}
return ret;
}
uint8_t pal_setup_amber_reg_value(uint8_t bus, char* dev_num, char* value) {
uint8_t dev_index = atoi(dev_num);
int ret;
int fd;
char fn[32];
uint8_t retry;
uint8_t tbuf[16] = {0};
uint8_t rbuf[16] = {0};
uint8_t ioexp_addr = 0xE8;
snprintf(fn, sizeof(fn), "/dev/i2c-%d", bus);
fd = open(fn, O_RDWR);
if(fd < 0) {
syslog(LOG_WARNING,"[%s]Cannot open bus %d", __func__, bus);
ret = PAL_ENOTSUP;
goto error_exit;
}
tbuf[0] = 0x06;
retry = MAX_READ_RETRY;
while(retry > 0) {
ret = i2c_rdwr_msg_transfer(fd, ioexp_addr, tbuf, 1, rbuf, 1);
if (PAL_EOK == ret) {
break;
}
msleep(50);
retry--;
}
if(ret < 0) {
syslog(LOG_WARNING,"[%s] Cannot read amber reg on bus %d", __func__, bus);
goto error_exit;
}
if(!strcmp(value, "on")) {
rbuf[0] &= ~(1 << dev_index);
} else {
rbuf[0] |= (1 << dev_index);
}
error_exit:
if (fd > 0) {
close(fd);
}
return rbuf[0];
}
int pal_set_amber_led(char *carrier, char* dev_num, char* value) {
int ret;
int fd;
char fn[32];
uint8_t retry;
uint8_t tbuf[16] = {0};
uint8_t rbuf[16] = {0};
uint8_t bus;
uint8_t ioexp_addr = 0xE8;
if(!strcmp(carrier, "carrier1")) {
bus = 21;
} else {
bus = 22;
}
pal_set_carrier_board_mux(bus);
pal_set_ioexp_direction(bus, "out");
snprintf(fn, sizeof(fn), "/dev/i2c-%d", bus);
fd = open(fn, O_RDWR);
if(fd < 0) {
syslog(LOG_WARNING,"[%s]Cannot open bus %d", __func__, bus);
ret = PAL_ENOTSUP;
goto error_exit;
}
tbuf[0] = 0x06;
tbuf[1] = pal_setup_amber_reg_value(bus, dev_num, value);
retry = MAX_READ_RETRY;
while(retry > 0) {
ret = i2c_rdwr_msg_transfer(fd, ioexp_addr, tbuf, 2, rbuf, 0);
if (PAL_EOK == ret) {
break;
}
msleep(50);
retry--;
}
if(ret < 0) {
syslog(LOG_WARNING,"[%s] Cannot set amber led on bus %d", __func__, bus);
goto error_exit;
}
error_exit:
if (fd > 0) {
close(fd);
}
return ret;
}
int pal_get_dev_guid(uint8_t fru, char *guid) {
pal_get_guid(OFFSET_DEV_GUID, g_dev_guid);
memcpy(guid, g_dev_guid, GUID_SIZE);
return 0;
}
int pal_get_cpld_reg_cmd(uint8_t reg, uint8_t cmd, uint8_t* state)
{
int fd = 0;
char fn[32];
uint8_t tbuf[16] = {0};
int ret = 0;
snprintf(fn, sizeof(fn), "/dev/i2c-%d", I2C_BUS_23);
fd = open(fn, O_RDWR);
if (fd < 0) {
syslog(LOG_WARNING, "[%s] Cannot open the i2c-%d", __func__, I2C_BUS_23);
ret = -1;
goto exit;
}
tbuf[0] = (cmd >> 8);
tbuf[1] = (cmd & 0x00FF);
ret = i2c_rdwr_msg_transfer(fd, reg, tbuf, 2, state, 1);
if (ret < 0) {
syslog(LOG_WARNING, "[%s] Cannot acces the i2c-%d dev: %x",
__func__, I2C_BUS_23, reg);
ret = -1;
goto exit;
}
ret = PAL_EOK;
exit:
if (fd > 0)
close(fd);
return ret;
}