diff options
Diffstat (limited to 'meta-raptor/meta-asus/recipes-asus/ipmid/files/platform')
10 files changed, 1810 insertions, 0 deletions
diff --git a/meta-raptor/meta-asus/recipes-asus/ipmid/files/platform/fruid.h b/meta-raptor/meta-asus/recipes-asus/ipmid/files/platform/fruid.h new file mode 100644 index 0000000..3580b08 --- /dev/null +++ b/meta-raptor/meta-asus/recipes-asus/ipmid/files/platform/fruid.h @@ -0,0 +1,28 @@ +/* + * + * Copyright 2015-present Facebook. All Rights Reserved. + * + * + * 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. + */ + +#ifndef __FRUID_H__ +#define __FRUID_H__ + +int plat_fruid_size(void); +int plat_fruid_data(int offset, int count, unsigned char *data); +int plat_fruid_init(void); + +#endif /* __FRUID_H__ */ diff --git a/meta-raptor/meta-asus/recipes-asus/ipmid/files/platform/sdr.c b/meta-raptor/meta-asus/recipes-asus/ipmid/files/platform/sdr.c new file mode 100644 index 0000000..e0a2f9a --- /dev/null +++ b/meta-raptor/meta-asus/recipes-asus/ipmid/files/platform/sdr.c @@ -0,0 +1,412 @@ +/* + * + * Copyright 2014-present Facebook. All Rights Reserved. + * + * This file represents platform specific implementation for storing + * SDR record entries and acts as back-end for IPMI stack + * + * + * 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 "sdr.h" +#include "sensor.h" +#include "timestamp.h" +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <errno.h> +#include <syslog.h> +#include <string.h> + +// SDR Header magic number +#define SDR_HDR_MAGIC 0xFBFBFBFB + +// SDR Header version number +#define SDR_HDR_VERSION 0x01 + +// SDR reservation IDs can not be 0x00 or 0xFFFF +#define SDR_RSVID_MIN 0x01 +#define SDR_RSVID_MAX 0xFFFE + +#define SDR_RECORDS_MAX 64 // to support around 64 sensors + +// SDR index to keep track +#define SDR_INDEX_MIN 0 +#define SDR_INDEX_MAX (SDR_RECORDS_MAX - 1) + +// Record ID can not be 0x0 (IPMI/Section 31) +#define SDR_RECID_MIN 1 +#define SDR_RECID_MAX SDR_RECORDS_MAX + +// Special RecID value for first and last (IPMI/Section 31) +#define SDR_RECID_FIRST 0x0000 +#define SDR_RECID_LAST 0xFFFF + +#define SDR_VERSION 0x51 +#define SDR_LEN_MAX 64 + +#define SDR_FULL_TYPE 0x01 +#define SDR_MGMT_TYPE 0x12 +#define SDR_OEM_TYPE 0xC0 + +#define SDR_FULL_LEN 64 +#define SDR_MGMT_LEN 32 +#define SDR_OEM_LEN 64 + +// SDR header struct to keep track of SEL Log entries +typedef struct { + int magic; // Magic number to check validity + int version; // version number of this header + int begin; // index to the first SDR entry + int end; // index to the last SDR entry + time_stamp_t ts_add; // last addition time stamp + time_stamp_t ts_erase; // last erase time stamp +} sdr_hdr_t; + +// Keep track of last Reservation ID +static int g_rsv_id = 0x01; + +// SDR Header and data global structures +static sdr_hdr_t g_sdr_hdr; +static sdr_rec_t g_sdr_data[SDR_RECORDS_MAX]; + +// Add a new SDR entry +static int +plat_sdr_add_entry(sdr_rec_t *rec, int *rec_id) { + // If SDR is full, return error + if (plat_sdr_num_entries() == SDR_RECORDS_MAX) { + syslog(LOG_ALERT, "plat_sdr_add_entry: SDR full\n"); + return -1; + } + + // Add Record ID which is array index + 1 + rec->rec[0] = g_sdr_hdr.end+1; + + // Add the enry at end + memcpy(g_sdr_data[g_sdr_hdr.end].rec, rec->rec, sizeof(sdr_rec_t)); + + // Return the newly added record ID + *rec_id = g_sdr_hdr.end+1; + + // Increment the end pointer + ++g_sdr_hdr.end; + + // Update timestamp for add in header + time_stamp_fill(g_sdr_hdr.ts_add.ts); + + return 0; +} + +static int +sdr_add_mgmt_rec(sensor_mgmt_t *p_rec) { + int rec_id = 0; + sdr_rec_t sdr = { 0 }; + sdr_mgmt_t rec = { 0 }; + + // Populate SDR MGMT record + rec.ver = SDR_VERSION; + rec.type = SDR_MGMT_TYPE; + rec.len = SDR_MGMT_LEN; + + rec.slave_addr = p_rec->slave_addr; + rec.chan_no = p_rec->chan_no; + + rec.pwr_state_init = p_rec->pwr_state_init; + rec.dev_caps = p_rec->dev_caps; + rec.ent_id = p_rec->ent_id; + rec.ent_inst = p_rec->ent_inst; + rec.oem = p_rec->oem; + rec.str_type_len = p_rec->str_type_len; + memcpy(rec.str, p_rec->str, SENSOR_STR_SIZE); + + // Copy this record to generic SDR record + memcpy(sdr.rec, &rec, SDR_LEN_MAX); + + // Add this record to SDR repo + if (plat_sdr_add_entry(&sdr, &rec_id)) { + syslog(LOG_ALERT, "sdr_add_mgmt_rec: plat_sdr_add_entry failed\n"); + return -1; + } + + return 0; +} + +static int +sdr_add_disc_rec(sensor_disc_t *p_rec) { + int rec_id = 0; + sdr_rec_t sdr = { 0 }; + sdr_full_t rec = { 0 }; + + // Populate SDR FULL record + rec.ver = SDR_VERSION; + rec.type = SDR_FULL_TYPE; + rec.len = SDR_FULL_LEN; + + rec.owner = p_rec->owner; + rec.lun = p_rec->lun; + + rec.ent_id = p_rec->ent_id; + rec.ent_inst = p_rec->ent_inst; + rec.sensor_init = p_rec->sensor_init; + rec.sensor_caps = p_rec->sensor_caps; + rec.sensor_type = p_rec->sensor_type; + rec.evt_read_type = p_rec->evt_read_type; + memcpy(rec.assert_evt_mask, p_rec->assert_evt_mask, 2); + memcpy(rec.deassert_evt_mask, p_rec->deassert_evt_mask, 2); + memcpy(rec.read_evt_mask, p_rec->read_evt_mask, 2); + rec.oem = p_rec->oem; + rec.str_type_len = p_rec->str_type_len; + memcpy(rec.str, p_rec->str, SENSOR_STR_SIZE); + + // Copy this record to generic SDR record + memcpy(sdr.rec, &rec, SDR_LEN_MAX); + + // Add this record to SDR repo + if (plat_sdr_add_entry(&sdr, &rec_id)) { + syslog(LOG_ALERT, "sdr_add_disc_rec: plat_sdr_add_entry failed\n"); + return -1; + } + + return 0; +} + +static int +sdr_add_thresh_rec(sensor_thresh_t *p_rec) { + int rec_id = 0; + sdr_rec_t sdr = { 0 }; + sdr_full_t rec = { 0 }; + + // Populate SDR FULL record + rec.ver = SDR_VERSION; + rec.type = SDR_FULL_TYPE; + rec.len = SDR_FULL_LEN; + + rec.owner = p_rec->owner; + rec.lun = p_rec->lun; + + rec.ent_id = p_rec->ent_id; + rec.ent_inst = p_rec->ent_inst; + rec.sensor_init = p_rec->sensor_init; + rec.sensor_caps = p_rec->sensor_caps; + rec.sensor_type = p_rec->sensor_type; + rec.evt_read_type = p_rec->evt_read_type; + memcpy(rec.lt_read_mask, p_rec->lt_read_mask, 2); + memcpy(rec.ut_read_mask, p_rec->ut_read_mask, 2); + memcpy(rec.set_thresh_mask, p_rec->set_thresh_mask, 2); + rec.sensor_units1 = p_rec->sensor_units1; + rec.sensor_units2 = p_rec->sensor_units2; + rec.sensor_units3 = p_rec->sensor_units3; + rec.linear = p_rec->linear; + rec.m_val = p_rec->m_val; + rec.m_tolerance = p_rec->m_tolerance; + rec.b_val = p_rec->b_val; + rec.b_accuracy = p_rec->b_accuracy; + rec.analog_flags = p_rec->analog_flags; + rec.nominal = p_rec->nominal; + rec.normal_max = p_rec->normal_max; + rec.normal_min = p_rec->normal_min; + rec.max_reading = p_rec->max_reading; + rec.min_reading = p_rec->min_reading; + rec.unr_thresh = p_rec->unr_thresh; + rec.uc_thresh = p_rec->uc_thresh; + rec.unc_thresh = p_rec->unc_thresh; + rec.lnr_thresh = p_rec->lnr_thresh; + rec.lc_thresh = p_rec->lc_thresh; + rec.lnc_thresh = p_rec->lnc_thresh; + rec.pos_hyst = p_rec->pos_hyst; + rec.neg_hyst = p_rec->neg_hyst; + rec.oem = p_rec->oem; + rec.str_type_len = p_rec->str_type_len; + memcpy(rec.str, p_rec->str, SENSOR_STR_SIZE); + + // Copy this record to generic SDR record + memcpy(sdr.rec, &rec, SDR_LEN_MAX); + + // Add this record to SDR repo + if (plat_sdr_add_entry(&sdr, &rec_id)) { + syslog(LOG_ALERT, "sdr_add_thresh_rec: plat_sdr_add_entry failed\n"); + return -1; + } + + return 0; +} + +static int +sdr_add_oem_rec(sensor_oem_t *p_rec) { + int rec_id = 0; + sdr_rec_t sdr = { 0 }; + sdr_oem_t rec = { 0 }; + + // Populate SDR OEM record + rec.ver = SDR_VERSION; + rec.type = SDR_OEM_TYPE; + rec.len = SDR_OEM_LEN; + + memcpy(rec.mfr_id, p_rec->mfr_id, 3); + memcpy(rec.oem_data, p_rec->oem_data, SENSOR_OEM_DATA_SIZE); + + // Copy this record to generic SDR record + memcpy(sdr.rec, &rec, SDR_LEN_MAX); + + // Add this record to SDR repo + if (plat_sdr_add_entry(&sdr, &rec_id)) { + syslog(LOG_ALERT, "sdr_add_oem_rec: plat_sdr_add_entry failed\n"); + return -1; + } + + return 0; +} + +// Platform specific SEL API entry points +// Retrieve time stamp for recent add operation +void +plat_sdr_ts_recent_add(time_stamp_t *ts) { + memcpy(ts->ts, g_sdr_hdr.ts_add.ts, 0x04); +} + +// Retrieve time stamp for recent erase operation +void +plat_sdr_ts_recent_erase(time_stamp_t *ts) { + memcpy(ts->ts, g_sdr_hdr.ts_erase.ts, 0x04); +} + +// Retrieve total number of entries in SDR repo +int +plat_sdr_num_entries(void) { + return (g_sdr_hdr.end - g_sdr_hdr.begin); +} + +// Retrieve total free space available in SDR repo +int +plat_sdr_free_space(void) { + int total_space; + int used_space; + + total_space = SDR_RECORDS_MAX * sizeof(sdr_rec_t); + used_space = plat_sdr_num_entries() * sizeof(sdr_rec_t); + + return (total_space - used_space); +} + +// Reserve an ID that will be used in later operations +// IPMI/Section 33.11 +int +plat_sdr_rsv_id() { + // Increment the current reservation ID and return + if (g_rsv_id++ == SDR_RSVID_MAX) { + g_rsv_id = SDR_RSVID_MIN; + } + + return g_rsv_id; +} + +// Get the SDR entry for a given record ID +// IPMI/Section 33.12 +int +plat_sdr_get_entry(int rsv_id, int read_rec_id, sdr_rec_t *rec, + int *next_rec_id) { + + int index; + + // Make sure the rsv_id matches + if (rsv_id != g_rsv_id) { + syslog(LOG_ALERT, "plat_sdr_get_entry: Reservation ID mismatch\n"); + return -1; + } + + // Find the index in to array based on given index + if (read_rec_id == SDR_RECID_FIRST) { + index = g_sdr_hdr.begin; + } else if (read_rec_id == SDR_RECID_LAST) { + index = g_sdr_hdr.end - 1; + } else { + index = read_rec_id - 1; + } + + // If the SDR repo is empty return error + if (plat_sdr_num_entries() == 0) { + syslog(LOG_ALERT, "plat_sdr_get_entry: No entries\n"); + return -1; + } + + // Check for boundary conditions + if ((index < SDR_INDEX_MIN) || (index > SDR_INDEX_MAX)) { + syslog(LOG_ALERT, "plat_sdr_get_entry: Invalid Record ID %d\n", read_rec_id); + return -1; + } + + // Check to make sure the given id is valid + if (index < g_sdr_hdr.begin || index >= g_sdr_hdr.end) { + syslog(LOG_ALERT, "plat_sdr_get_entry: Wrong Record ID %d\n", read_rec_id); + return -1; + } + + memcpy(rec->rec, g_sdr_data[index].rec, sizeof(sdr_rec_t)); + + // Return the next record ID in the log + *next_rec_id = ++read_rec_id; + + // If this is the last entry in the log, return 0xFFFF + if (*next_rec_id == g_sdr_hdr.end) { + *next_rec_id = SDR_RECID_LAST; + } + + return 0; +} + + +// Initialize SDR Repo structure +int +plat_sdr_init(void) { + int num; + sensor_mgmt_t *p_mgmt; + sensor_thresh_t *p_thresh; + sensor_disc_t *p_disc; + sensor_oem_t *p_oem; + + // Populate SDR Header + g_sdr_hdr.magic = SDR_HDR_MAGIC; + g_sdr_hdr.version = SDR_HDR_VERSION; + g_sdr_hdr.begin = SDR_INDEX_MIN; + g_sdr_hdr.end = SDR_INDEX_MIN; + memset(g_sdr_hdr.ts_add.ts, 0x0, 4); + memset(g_sdr_hdr.ts_erase.ts, 0x0, 4); + + // Populate all mgmt control sensors + plat_sensor_mgmt_info(&num, &p_mgmt); + for (int i = 0; i < num; i++) { + sdr_add_mgmt_rec(&p_mgmt[i]); + } + + // Populate all discrete sensors + plat_sensor_disc_info(&num, &p_disc); + for (int i = 0; i < num; i++) { + sdr_add_disc_rec(&p_disc[i]); + } + + // Populate all threshold sensors + plat_sensor_thresh_info(&num, &p_thresh); + for (int i = 0; i < num; i++) { + sdr_add_thresh_rec(&p_thresh[i]); + } + + // Populate all OEM sensors + plat_sensor_oem_info(&num, &p_oem); + for (int i = 0; i < num; i++) { + sdr_add_oem_rec(&p_oem[i]); + } + + return 0; +} diff --git a/meta-raptor/meta-asus/recipes-asus/ipmid/files/platform/sdr.h b/meta-raptor/meta-asus/recipes-asus/ipmid/files/platform/sdr.h new file mode 100644 index 0000000..5e2a591 --- /dev/null +++ b/meta-raptor/meta-asus/recipes-asus/ipmid/files/platform/sdr.h @@ -0,0 +1,132 @@ +/* + * + * Copyright 2014-present Facebook. All Rights Reserved. + * + * + * 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. + */ + +#ifndef __SDR_H__ +#define __SDR_H__ + +#include "timestamp.h" + +typedef struct { + unsigned char rec[64]; +} sdr_rec_t; + +// Full Sensor SDR record; IPMI/Section 43.1 +typedef struct { + // Sensor Record Header + unsigned char rec_id[2]; + unsigned char ver; + unsigned char type; + unsigned char len; + // Record Key Bytes + unsigned char owner; + unsigned char lun; + unsigned char sensor_num; + // Record Body Bytes + unsigned char ent_id; + unsigned char ent_inst; + unsigned char sensor_init; + unsigned char sensor_caps; + unsigned char sensor_type; + unsigned char evt_read_type; + union { + unsigned char assert_evt_mask[2]; + unsigned char lt_read_mask[2]; + }; + union { + unsigned char deassert_evt_mask[2]; + unsigned char ut_read_mask[2]; + }; + union { + unsigned char read_evt_mask[2]; + unsigned char set_thresh_mask[2]; + }; + unsigned char sensor_units1; + unsigned char sensor_units2; + unsigned char sensor_units3; + unsigned char linear; + unsigned char m_val; + unsigned char m_tolerance; + unsigned char b_val; + unsigned char b_accuracy; + unsigned char accuracy_dir; + unsigned char rb_exp; + unsigned char analog_flags; + unsigned char nominal; + unsigned char normal_max; + unsigned char normal_min; + unsigned char max_reading; + unsigned char min_reading; + unsigned char unr_thresh; + unsigned char uc_thresh; + unsigned char unc_thresh; + unsigned char lnr_thresh; + unsigned char lc_thresh; + unsigned char lnc_thresh; + unsigned char pos_hyst; + unsigned char neg_hyst; + unsigned char rsvd[2]; + unsigned char oem; + unsigned char str_type_len; + char str[16]; +} sdr_full_t; + +// Mgmt. Controller SDR record; IPMI/ Section 43.9 +typedef struct { + // Sensor Record Header + unsigned char rec_id[2]; + unsigned char ver; + unsigned char type; + unsigned char len; + // Record Key Bytes + unsigned char slave_addr; + unsigned char chan_no; + // Record Body Bytes + unsigned char pwr_state_init; + unsigned char dev_caps; + unsigned char rsvd[3]; + unsigned char ent_id; + unsigned char ent_inst; + unsigned char oem; + unsigned char str_type_len; + char str[16]; +} sdr_mgmt_t; + +// OEM type SDR record; IPMI/Section 43.12 +typedef struct { + // Sensor Record Header + unsigned char rec_id[2]; + unsigned char ver; + unsigned char type; + unsigned char len; + // Record Body Bytes + unsigned char mfr_id[3]; + unsigned char oem_data[56]; +} sdr_oem_t; + +void plat_sdr_ts_recent_add(time_stamp_t *ts); +void plat_sdr_ts_recent_erase(time_stamp_t *ts); +int plat_sdr_num_entries(void); +int plat_sdr_free_space(void); +int plat_sdr_rsv_id(); +int plat_sdr_get_entry(int rsv_id, int read_rec_id, sdr_rec_t *rec, + int *next_rec_id); +int plat_sdr_init(void); + +#endif /* __SDR_H__ */ diff --git a/meta-raptor/meta-asus/recipes-asus/ipmid/files/platform/sel.c b/meta-raptor/meta-asus/recipes-asus/ipmid/files/platform/sel.c new file mode 100644 index 0000000..a7aa78f --- /dev/null +++ b/meta-raptor/meta-asus/recipes-asus/ipmid/files/platform/sel.c @@ -0,0 +1,438 @@ +/* + * + * Copyright 2014-present Facebook. All Rights Reserved. + * + * This file represents platform specific implementation for storing + * SEL logs and acts as back-end for IPMI stack + * + * TODO: Optimize the file handling to keep file open always instead of + * current open/seek/close + * + * + * 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 "sel.h" +#include "timestamp.h" +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <errno.h> +#include <syslog.h> +#include <string.h> + +// SEL File. +#define SEL_LOG_FILE "/mnt/data/sel.bin" + +// SEL Header magic number +#define SEL_HDR_MAGIC 0xFBFBFBFB + +// SEL Header version number +#define SEL_HDR_VERSION 0x01 + +// SEL Data offset from file beginning +#define SEL_DATA_OFFSET 0x100 + +// SEL reservation IDs can not be 0x00 or 0xFFFF +#define SEL_RSVID_MIN 0x01 +#define SEL_RSVID_MAX 0xFFFE + +// Number of SEL records before wrap +#define SEL_RECORDS_MAX 128 // TODO: Based on need we can make it bigger +#define SEL_ELEMS_MAX (SEL_RECORDS_MAX+1) + +// Index for circular array +#define SEL_INDEX_MIN 0x00 +#define SEL_INDEX_MAX SEL_RECORDS_MAX + +// Record ID can not be 0x0 (IPMI/Section 31) +#define SEL_RECID_MIN (SEL_INDEX_MIN+1) +#define SEL_RECID_MAX (SEL_INDEX_MAX+1) + +// Special RecID value for first and last (IPMI/Section 31) +#define SEL_RECID_FIRST 0x0000 +#define SEL_RECID_LAST 0xFFFF + +// SEL header struct to keep track of SEL Log entries +typedef struct { + int magic; // Magic number to check validity + int version; // version number of this header + int begin; // index to the begining of the log + int end; // index to end of the log + time_stamp_t ts_add; // last addition time stamp + time_stamp_t ts_erase; // last erase time stamp +} sel_hdr_t; + +// Keep track of last Reservation ID +static int g_rsv_id = 0x01; + +// Cached version of SEL Header and data +static sel_hdr_t g_sel_hdr; +static sel_msg_t g_sel_data[SEL_ELEMS_MAX]; + +// Local helper functions to interact with file system +static int +file_get_sel_hdr(void) { + FILE *fp; + + fp = fopen(SEL_LOG_FILE, "r"); + if (fp == NULL) { + return -1; + } + + if (fread(&g_sel_hdr, sizeof(sel_hdr_t), 1, fp) <= 0) { + syslog(LOG_ALERT, "file_get_sel_hdr: fread\n"); + fclose (fp); + return -1; + } + + fclose(fp); + return 0; +} + +static int +file_get_sel_data(void) { + FILE *fp; + + fp = fopen(SEL_LOG_FILE, "r"); + if (fp == NULL) { + syslog(LOG_ALERT, "file_get_sel_data: fopen\n"); + return -1; + } + + if (fseek(fp, SEL_DATA_OFFSET, SEEK_SET)) { + syslog(LOG_ALERT, "file_get_sel_data: fseek\n"); + fclose(fp); + return -1; + } + + unsigned char buf[SEL_ELEMS_MAX * 16]; + if (fread(buf, 1, SEL_ELEMS_MAX * sizeof(sel_msg_t), fp) <= 0) { + syslog(LOG_ALERT, "file_get_sel_data: fread\n"); + fclose(fp); + return -1; + } + + fclose(fp); + + for (int i = 0; i < SEL_ELEMS_MAX; i++) { + for (int j = 0; j < sizeof(sel_msg_t);j++) { + g_sel_data[i].msg[j] = buf[i*16 + j]; + } + } + + return 0; +} + +static int +file_store_sel_hdr(void) { + FILE *fp; + + fp = fopen(SEL_LOG_FILE, "r+"); + if (fp == NULL) { + syslog(LOG_ALERT, "file_store_sel_hdr: fopen\n"); + return -1; + } + + if (fwrite(&g_sel_hdr, sizeof(sel_hdr_t), 1, fp) <= 0) { + syslog(LOG_ALERT, "file_store_sel_hdr: fwrite\n"); + fclose(fp); + return -1; + } + + fclose(fp); + + return 0; +} + +static int +file_store_sel_data(int recId, sel_msg_t *data) { + FILE *fp; + int index; + + fp = fopen(SEL_LOG_FILE, "r+"); + if (fp == NULL) { + syslog(LOG_ALERT, "file_store_sel_data: fopen\n"); + return -1; + } + + // Records are stored using zero-based index + index = (recId-1) * sizeof(sel_msg_t); + + if (fseek(fp, SEL_DATA_OFFSET+index, SEEK_SET)) { + syslog(LOG_ALERT, "file_store_sel_data: fseek\n"); + fclose(fp); + return -1; + } + + if (fwrite(data->msg, sizeof(sel_msg_t), 1, fp) <= 0) { + syslog(LOG_ALERT, "file_store_sel_data: fwrite\n"); + fclose(fp); + return -1; + } + + fclose(fp); + + return 0; +} + +// Platform specific SEL API entry points +// Retrieve time stamp for recent add operation +void +plat_sel_ts_recent_add(time_stamp_t *ts) { + memcpy(ts->ts, g_sel_hdr.ts_add.ts, 0x04); +} + +// Retrieve time stamp for recent erase operation +void +plat_sel_ts_recent_erase(time_stamp_t *ts) { + memcpy(ts->ts, g_sel_hdr.ts_erase.ts, 0x04); +} + +// Retrieve total number of entries in SEL log +int +plat_sel_num_entries(void) { + if (g_sel_hdr.begin <= g_sel_hdr.end) { + return (g_sel_hdr.end - g_sel_hdr.begin); + } else { + return (g_sel_hdr.end + (SEL_INDEX_MAX - g_sel_hdr.begin + 1)); + } +} + +// Retrieve total free space available in SEL log +int +plat_sel_free_space(void) { + int total_space; + int used_space; + + total_space = SEL_RECORDS_MAX * sizeof(sel_msg_t); + used_space = plat_sel_num_entries() * sizeof(sel_msg_t); + + return (total_space - used_space); +} + +// Reserve an ID that will be used in later operations +// IPMI/Section 31.4 +int +plat_sel_rsv_id() { + // Increment the current reservation ID and return + if (g_rsv_id++ == SEL_RSVID_MAX) { + g_rsv_id = SEL_RSVID_MIN; + } + + return g_rsv_id; +} + +// Get the SEL entry for a given record ID +// IPMI/Section 31.5 +int +plat_sel_get_entry(int read_rec_id, sel_msg_t *msg, int *next_rec_id) { + + int index; + + // Find the index in to array based on given index + if (read_rec_id == SEL_RECID_FIRST) { + index = g_sel_hdr.begin; + } else if (read_rec_id == SEL_RECID_LAST) { + if (g_sel_hdr.end) { + index = g_sel_hdr.end - 1; + } else { + index = SEL_INDEX_MAX; + } + } else { + index = read_rec_id - 1; + } + + // If the log is empty return error + if (plat_sel_num_entries() == 0) { + syslog(LOG_ALERT, "plat_sel_get_entry: No entries\n"); + return -1; + } + + // Check for boundary conditions + if ((index < SEL_INDEX_MIN) || (index > SEL_INDEX_MAX)) { + syslog(LOG_ALERT, "plat_sel_get_entry: Invalid Record ID %d\n", read_rec_id); + return -1; + } + + // If begin < end, check to make sure the given id falls between + if (g_sel_hdr.begin < g_sel_hdr.end) { + if (index < g_sel_hdr.begin || index >= g_sel_hdr.end) { + syslog(LOG_ALERT, "plat_sel_get_entry: Wrong Record ID %d\n", read_rec_id); + return -1; + } + } + + // If end < begin, check to make sure the given id is valid + if (g_sel_hdr.begin > g_sel_hdr.end) { + if (index >= g_sel_hdr.end && index < g_sel_hdr.begin) { + syslog(LOG_ALERT, "plat_sel_get_entry: Wrong Record ID2 %d\n", read_rec_id); + return -1; + } + } + + memcpy(msg->msg, g_sel_data[index].msg, sizeof(sel_msg_t)); + + // Return the next record ID in the log + *next_rec_id = read_rec_id++; + if (*next_rec_id > SEL_INDEX_MAX) { + *next_rec_id = SEL_INDEX_MIN; + } + + // If this is the last entry in the log, return 0xFFFF + if (*next_rec_id == g_sel_hdr.end) { + *next_rec_id = SEL_RECID_LAST; + } + + return 0; +} + +// Add a new entry in to SEL log +// IPMI/Section 31.6 +int +plat_sel_add_entry(sel_msg_t *msg, int *rec_id) { + // If the SEL if full, roll over. To keep track of empty condition, use + // one empty location less than the max records. + if (plat_sel_num_entries() == SEL_RECORDS_MAX) { + syslog(LOG_ALERT, "plat_sel_add_entry: SEL rollover\n"); + if (++g_sel_hdr.begin > SEL_INDEX_MAX) { + g_sel_hdr.begin = SEL_INDEX_MIN; + } + } + + // Update message's time stamp starting at byte 4 + time_stamp_fill(&msg->msg[3]); + + // Add the enry at end + memcpy(g_sel_data[g_sel_hdr.end].msg, msg->msg, sizeof(sel_msg_t)); + + // Return the newly added record ID + *rec_id = g_sel_hdr.end+1; + + if (file_store_sel_data(*rec_id, msg)) { + syslog(LOG_ALERT, "plat_sel_add_entry: file_store_sel_data\n"); + return -1; + } + + // Increment the end pointer + if (++g_sel_hdr.end > SEL_INDEX_MAX) { + g_sel_hdr.end = SEL_INDEX_MIN; + } + + // Update timestamp for add in header + time_stamp_fill(g_sel_hdr.ts_add.ts); + + // Store the structure persistently + if (file_store_sel_hdr()) { + syslog(LOG_ALERT, "plat_sel_add_entry: file_store_sel_hdr\n"); + return -1; + } + + return 0; +} + +// Erase the SEL completely +// IPMI/Section 31.9 +// Note: To reduce wear/tear, instead of erasing, manipulating the metadata +int +plat_sel_erase(int rsv_id) { + if (rsv_id != g_rsv_id) { + return -1; + } + + // Erase SEL Logs + g_sel_hdr.begin = SEL_INDEX_MIN; + g_sel_hdr.end = SEL_INDEX_MIN; + + // Update timestamp for erase in header + time_stamp_fill(g_sel_hdr.ts_erase.ts); + + // Store the structure persistently + if (file_store_sel_hdr()) { + syslog(LOG_ALERT, "plat_sel_erase: file_store_sel_hdr\n"); + return -1; + } + + return 0; +} + +// To get the erase status while erase happens +// IPMI/Section 31.2 +// Note: Since we are not doing offline erasing, need not return in-progress state +int +plat_sel_erase_status(int rsv_id, sel_erase_stat_t *status) { + if (rsv_id != g_rsv_id) { + return -1; + } + + // Since we do not do any offline erasing, always return erase done + *status = SEL_ERASE_DONE; + + return 0; +} + +// Initialize SEL log file +int +plat_sel_init(void) { + FILE *fp; + + // Check if the file exists or not + if (access(SEL_LOG_FILE, F_OK) == 0) { + // Since file is present, fetch all the contents to cache + if (file_get_sel_hdr()) { + syslog(LOG_ALERT, "plat_init_sel: file_get_sel_hdr\n"); + return -1; + } + + if (file_get_sel_data()) { + syslog(LOG_ALERT, "plat_init_sel: file_get_sel_data\n"); + return -1; + } + + return 0; + } + + // File not present, so create the file + fp = fopen(SEL_LOG_FILE, "w+"); + if (fp == NULL) { + syslog(LOG_ALERT, "plat_init_sel: fopen\n"); + return -1; + } + + fclose (fp); + + // Populate SEL Header in to the file + g_sel_hdr.magic = SEL_HDR_MAGIC; + g_sel_hdr.version = SEL_HDR_VERSION; + g_sel_hdr.begin = SEL_INDEX_MIN; + g_sel_hdr.end = SEL_INDEX_MIN; + memset(g_sel_hdr.ts_add.ts, 0x0, 4); + memset(g_sel_hdr.ts_erase.ts, 0x0, 4); + + if (file_store_sel_hdr()) { + syslog(LOG_ALERT, "plat_init_sel: file_store_sel_hdr\n"); + return -1; + } + + // Populate SEL Data in to the file + for (int i = 1; i <= SEL_RECORDS_MAX; i++) { + sel_msg_t msg = {0}; + if (file_store_sel_data(i, &msg)) { + syslog(LOG_ALERT, "plat_init_sel: file_store_sel_data\n"); + return -1; + } + } + + return 0; +} diff --git a/meta-raptor/meta-asus/recipes-asus/ipmid/files/platform/sel.h b/meta-raptor/meta-asus/recipes-asus/ipmid/files/platform/sel.h new file mode 100644 index 0000000..81dbcdf --- /dev/null +++ b/meta-raptor/meta-asus/recipes-asus/ipmid/files/platform/sel.h @@ -0,0 +1,51 @@ +/* + * + * Copyright 2014-present Facebook. All Rights Reserved. + * + * + * 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. + */ + +#ifndef __SEL_H__ +#define __SEL_H__ + +#include "timestamp.h" + +enum { + IPMI_SEL_INIT_ERASE = 0xAA, + IPMI_SEL_ERASE_STAT = 0x00, +}; + +typedef enum { + SEL_ERASE_IN_PROG = 0x00, + SEL_ERASE_DONE = 0x01, +} sel_erase_stat_t; + +typedef struct { + unsigned char msg[16]; +} sel_msg_t; + +void plat_sel_ts_recent_add(time_stamp_t *ts); +void plat_sel_ts_recent_erase(time_stamp_t *ts); +int plat_sel_num_entries(void); +int plat_sel_free_space(void); +int plat_sel_rsv_id(); +int plat_sel_get_entry(int read_rec_id, sel_msg_t *msg, int *next_rec_id); +int plat_sel_add_entry(sel_msg_t *msg, int *rec_id); +int plat_sel_erase(int rsv_id); +int plat_sel_erase_status(int rsv_id, sel_erase_stat_t *status); +int plat_sel_init(void); + +#endif /* __SEL_H__ */ diff --git a/meta-raptor/meta-asus/recipes-asus/ipmid/files/platform/sensor.h b/meta-raptor/meta-asus/recipes-asus/ipmid/files/platform/sensor.h new file mode 100644 index 0000000..5d8c11a --- /dev/null +++ b/meta-raptor/meta-asus/recipes-asus/ipmid/files/platform/sensor.h @@ -0,0 +1,117 @@ +/* + * + * Copyright 2014-present Facebook. All Rights Reserved. + * + * + * 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. + */ + +#ifndef __SENSOR_H__ +#define __SENSOR_H__ + +#include "timestamp.h" + +#define IANA_ID_SIZE 3 +#define SENSOR_STR_SIZE 16 +#define SENSOR_OEM_DATA_SIZE 56 + +// Threshold Sensor Descriptor +typedef struct { + unsigned char owner; + unsigned char lun; + unsigned char sensor_num; + unsigned char ent_id; + unsigned char ent_inst; + unsigned char sensor_init; + unsigned char sensor_caps; + unsigned char sensor_type; + unsigned char evt_read_type; + unsigned char lt_read_mask[2]; + unsigned char ut_read_mask[2]; + unsigned char set_thresh_mask[2]; + unsigned char sensor_units1; + unsigned char sensor_units2; + unsigned char sensor_units3; + unsigned char linear; + unsigned char m_val; + unsigned char m_tolerance; + unsigned char b_val; + unsigned char b_accuracy; + unsigned char accuracy_dir; + unsigned char rb_exp; + unsigned char analog_flags; + unsigned char nominal; + unsigned char normal_max; + unsigned char normal_min; + unsigned char max_reading; + unsigned char min_reading; + unsigned char unr_thresh; + unsigned char uc_thresh; + unsigned char unc_thresh; + unsigned char lnr_thresh; + unsigned char lc_thresh; + unsigned char lnc_thresh; + unsigned char pos_hyst; + unsigned char neg_hyst; + unsigned char oem; + unsigned char str_type_len; + char str[SENSOR_STR_SIZE]; +} sensor_thresh_t; + +// Discrete Sensor Descriptor +typedef struct { + unsigned char owner; + unsigned char lun; + unsigned char sensor_num; + unsigned char ent_id; + unsigned char ent_inst; + unsigned char sensor_init; + unsigned char sensor_caps; + unsigned char sensor_type; + unsigned char evt_read_type; + unsigned char assert_evt_mask[2]; + unsigned char deassert_evt_mask[2]; + unsigned char read_evt_mask[2]; + unsigned char oem; + unsigned char str_type_len; + char str[SENSOR_STR_SIZE]; +} sensor_disc_t; + +// Mgmt. Controller Sensor Descriptor +typedef struct { + unsigned char slave_addr; + unsigned char chan_no; + unsigned char pwr_state_init; + unsigned char dev_caps; + unsigned char ent_id; + unsigned char ent_inst; + unsigned char oem; + unsigned char str_type_len; + char str[SENSOR_STR_SIZE]; +} sensor_mgmt_t; + +// OEM type Sensor Descriptor +typedef struct { + unsigned char mfr_id[IANA_ID_SIZE]; + unsigned char oem_data[SENSOR_OEM_DATA_SIZE]; +} sensor_oem_t; + +void plat_sensor_mgmt_info(int *num, sensor_mgmt_t **p_sensor); +void plat_sensor_disc_info(int *num, sensor_disc_t **p_sensor); +void plat_sensor_thresh_info(int *num, sensor_thresh_t **p_sensor); +void plat_sensor_oem_info(int *num, sensor_oem_t **p_sensor); +int plat_sensor_init(void); + +#endif /* __SENSOR_H__ */ diff --git a/meta-raptor/meta-asus/recipes-asus/ipmid/files/platform/timestamp.c b/meta-raptor/meta-asus/recipes-asus/ipmid/files/platform/timestamp.c new file mode 100644 index 0000000..11ac03e --- /dev/null +++ b/meta-raptor/meta-asus/recipes-asus/ipmid/files/platform/timestamp.c @@ -0,0 +1,46 @@ +/* + * + * Copyright 2014-present Facebook. All Rights Reserved. + * + * This file is a helper file to fill timestamps from platform + * used by SEL Logs, SDR records etc. + * + * 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 <stdlib.h> +#include <unistd.h> +#include <errno.h> +#include <syslog.h> +#include <string.h> +#include <sys/time.h> +#include <time.h> + +// Local helper function to fill time stamp +void +time_stamp_fill(unsigned char *ts) { + unsigned int time; + struct timeval tv; + + gettimeofday(&tv, NULL); + + time = tv.tv_sec; + ts[0] = time & 0xFF; + ts[1] = (time >> 8) & 0xFF; + ts[2] = (time >> 16) & 0xFF; + ts[3] = (time >> 24) & 0xFF; + + return; +} diff --git a/meta-raptor/meta-asus/recipes-asus/ipmid/files/platform/timestamp.h b/meta-raptor/meta-asus/recipes-asus/ipmid/files/platform/timestamp.h new file mode 100644 index 0000000..430dd23 --- /dev/null +++ b/meta-raptor/meta-asus/recipes-asus/ipmid/files/platform/timestamp.h @@ -0,0 +1,30 @@ +/* + * + * Copyright 2014-present Facebook. All Rights Reserved. + * + * + * 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. + */ + +#ifndef __TIMESTAMP_H__ +#define __TIMESTAMP_H__ + +typedef struct { + unsigned char ts[4]; +} time_stamp_t; + +void time_stamp_fill(unsigned char *ts); + +#endif /* __TIMESTAMP_H__ */ diff --git a/meta-raptor/meta-asus/recipes-asus/ipmid/files/platform/wedge/fruid.c b/meta-raptor/meta-asus/recipes-asus/ipmid/files/platform/wedge/fruid.c new file mode 100644 index 0000000..5076ebe --- /dev/null +++ b/meta-raptor/meta-asus/recipes-asus/ipmid/files/platform/wedge/fruid.c @@ -0,0 +1,185 @@ +/* + * + * Copyright 2015-present Facebook. All Rights Reserved. + * + * This file provides platform specific implementation of FRUID information + * + * FRUID specification can be found at + * www.intel.com/content/dam/www/public/us/en/documents/product-briefs/platform-management-fru-document-rev-1-2-feb-2013.pdf + * + * + * 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 "../fruid.h" +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <errno.h> +#include <syslog.h> +#include <string.h> +//#include <facebook/wedge_eeprom.h> + +#define WEDGE_FRUID_SIZE 0x100 + +#define COMMON_HDR_VER 1 +#define PROD_INFO_VER 1 + +#define PROD_INFO_AREA_OFFSET 0x10 +#define PROD_INFO_CKSUM_OFFSET (PROD_INFO_AREA_OFFSET + 1) +#define LANG_CODE_ENGLISH 25 +#define TYPE_STR 0xC0 +#define TYPE_LAST 0xC1 +#define ZERO_CKSUM_CONST 0x100 +#define LEN_BYTE_SIZE 8 + +typedef struct _fruid_common_hdr_t { + unsigned char ver; + unsigned char internal_use_area_offset; + unsigned char chassis_info_area_offset; + unsigned char board_info_area_offset; + unsigned char prod_info_area_offset; + unsigned char multi_record_area_offset; + unsigned char padding; + unsigned char cksum; +} fruid_common_hdr_t; + +// Global structures +static unsigned char g_fruid[WEDGE_FRUID_SIZE] = {0}; + +static void +populate_fruid(void) { + + memset(&g_fruid, sizeof(g_fruid), 0); + +#if 0 + fruid_common_hdr_t *chdr = g_fruid; + + // Set Common Header version + chdr->ver = COMMON_HDR_VER; + + // Product Info Area offset in multiples of 8 bytes + chdr->prod_info_area_offset = PROD_INFO_AREA_OFFSET/LEN_BYTE_SIZE; + + // Calculate zero checksum + chdr->cksum = chdr->ver + chdr->prod_info_area_offset; + chdr->cksum = ZERO_CKSUM_CONST - chdr->cksum; + + // Retrieve Wedge EEPROM content + struct wedge_eeprom_st eeprom; + int rc = 0; + rc = wedge_eeprom_parse(NULL, &eeprom); + if (rc) + { + syslog(LOG_ALERT, "populate_fruid: wedge_eeprom_parse returns %d\n", rc); + return; + } + + // Start index at beginning of product info area + int i = PROD_INFO_AREA_OFFSET; + g_fruid[i++] = PROD_INFO_VER; + g_fruid[i++] = 0x00; // prod area length; filled at end + g_fruid[i++] = LANG_CODE_ENGLISH; + +#define _APPEND_STR_VALUE(name) do { \ + if (sizeof(name) < 1 || i + 1 + sizeof(name) >= sizeof(g_fruid)) { \ + break; \ + } \ + g_fruid[i++] = TYPE_STR + sizeof(name); \ + memcpy(&g_fruid[i], name, sizeof(name)); \ + i += sizeof(name); \ +} while(0) + + // Fill system manufacturer field + + _APPEND_STR_VALUE(eeprom.fbw_system_manufacturer); + + // Fill product name field + _APPEND_STR_VALUE(eeprom.fbw_product_name); + + // Fill product number field + _APPEND_STR_VALUE(eeprom.fbw_product_number); + + // convert product version to string and fill + char vbuf[5] = {0}; + snprintf(vbuf, sizeof(vbuf), "%0X", eeprom.fbw_product_version); + _APPEND_STR_VALUE(vbuf); + + // Fill product serial number field + _APPEND_STR_VALUE(eeprom.fbw_product_serial); + + // Fill product asset tag field + _APPEND_STR_VALUE(eeprom.fbw_product_asset); + + // Fill fruid file with dummy file name + char fruid_file_name[] = "fruid_1.0"; + _APPEND_STR_VALUE(fruid_file_name); + + // Field to indicate the last entry + g_fruid[i++] = TYPE_LAST; + + // length of the area in multiples of 8 bytes + int len = i-PROD_INFO_AREA_OFFSET+1; + if (len % LEN_BYTE_SIZE){ + // For non-multiple of 8 bytes, add one for partial data + g_fruid[PROD_INFO_CKSUM_OFFSET] = len/LEN_BYTE_SIZE + 1; + // And also increment index to keep checksum byte + i += (len % LEN_BYTE_SIZE); + } else { + g_fruid[PROD_INFO_CKSUM_OFFSET] = len/LEN_BYTE_SIZE; + } + + // Calculate zero checksum by adding all the values in product info area + for (int j = PROD_INFO_AREA_OFFSET; j < i; j++) { + g_fruid[i] += g_fruid[j]; + } + + // Calculate final cksum by subtraction + g_fruid[i] = ZERO_CKSUM_CONST - g_fruid[i]; + +#undef _APPEND_STR_VALUE +#endif + + return; +} + +// Access functions for FRUID +int +plat_fruid_size(void) { + return WEDGE_FRUID_SIZE; +} + +int +plat_fruid_data(int offset, int count, unsigned char *data) { + // Check for the boundary condition + if ((offset + count) > WEDGE_FRUID_SIZE) { + return -1; + } + + // Copy the FRUID content from the global structure + memcpy(data, &(g_fruid[offset]), count); + + return 0; +} + +// Initialize FRUID +int +plat_fruid_init(void) { + + // Populate FRUID global structure + populate_fruid(); + + return 0; +} diff --git a/meta-raptor/meta-asus/recipes-asus/ipmid/files/platform/wedge/sensor.c b/meta-raptor/meta-asus/recipes-asus/ipmid/files/platform/wedge/sensor.c new file mode 100644 index 0000000..ce3d4fb --- /dev/null +++ b/meta-raptor/meta-asus/recipes-asus/ipmid/files/platform/wedge/sensor.c @@ -0,0 +1,371 @@ +/* + * + * Copyright 2014-present Facebook. All Rights Reserved. + * + * This file provides platform specific implementation of sensor information + * + * + * 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 "../sensor.h" +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <errno.h> +#include <syslog.h> +#include <string.h> + +#define SENSOR_MGMT_MAX 1 +#define SENSOR_DISC_MAX 8 +#define SENSOR_THRESH_MAX 1 +#define SENSOR_OEM_MAX 1 + +#define BMC_SLAVE_ADDR 0x20 + +typedef struct { + unsigned char num; + sensor_mgmt_t sensor[SENSOR_MGMT_MAX]; +} sensor_mgmt_info_t; + +typedef struct { + unsigned char num; + sensor_disc_t sensor[SENSOR_DISC_MAX]; +} sensor_disc_info_t; + +typedef struct { + unsigned char num; + sensor_thresh_t sensor[SENSOR_THRESH_MAX]; +} sensor_thresh_info_t; + +typedef struct { + unsigned char num; + sensor_oem_t sensor[SENSOR_OEM_MAX]; +} sensor_oem_info_t; + +// Global structures +static sensor_mgmt_info_t g_sensor_mgmt = {0}; +static sensor_disc_info_t g_sensor_disc = {0}; +static sensor_thresh_info_t g_sensor_thresh = {0}; +static sensor_oem_info_t g_sensor_oem = {0}; + +static void +populate_mgmt_sensors(void) { + sensor_mgmt_t sensor = {0}; + + // Add record for the AST2100 BMC + sensor.slave_addr = BMC_SLAVE_ADDR; + sensor.chan_no = 0x0; // Primary BMC controller + + // Init Agent = false + sensor.pwr_state_init = 0x00; + + // FRUID = true, SEL = true, SDR = true, Sensor = true + sensor.dev_caps = 0x0F; + + // Device ID string + // Type - 0xC0: ASCII, Length - 0x09 + sensor.str_type_len = 0xC0 + 0x09; + strncpy(sensor.str, "Wedge-BMC", 0x09); + + // Add this sensor to the global table + if (g_sensor_mgmt.num >= SENSOR_MGMT_MAX) { + syslog(LOG_ALERT, "populate_mgmt_sensors: num exceeded\n"); + return; + } + + memcpy(&g_sensor_mgmt.sensor[g_sensor_mgmt.num], &sensor, sizeof(sensor_mgmt_t)); + + g_sensor_mgmt.num++; + + return; +} + +static void +populate_disc_sensors(void) { + + sensor_disc_t sensor = {0}; + + // Sensor uS Status + // Sensor# 0x10 + // EntitiyId# 0xD0, EntityInst# 0x00 + // Sensor Type# Chassis 0x18 + // Event Read/Type# OEM 0x70 + sensor.owner= BMC_SLAVE_ADDR; + sensor.lun = 0x00; + sensor.sensor_num = 0x10; + + sensor.ent_id = 0xD0; + sensor.ent_inst = 0x00; + // Enable Scanning, Enable Events + sensor.sensor_init = 0x63; + // Supports Auto Re-Arm + sensor.sensor_caps = 0x40; + sensor.sensor_type = 0x18; + sensor.evt_read_type = 0x70; + // 1-bit for CPU0 Thermal Trip + sensor.assert_evt_mask[0] = 0x04; + sensor.deassert_evt_mask[0] = 0x00; + sensor.read_evt_mask[0] = 0x04; + + // Device ID string + // Type - 0xC0: ASCII, Length - 12 + sensor.str_type_len = 0xC0 + 9; + strncpy(sensor.str, "uS-Status", 9); + + // Add this sensor to the global table + if (g_sensor_disc.num >= SENSOR_DISC_MAX) { + syslog(LOG_ALERT, "populate_disc_sensors: num exceeded\n"); + return; + } + + memcpy(&g_sensor_disc.sensor[g_sensor_disc.num], &sensor, sizeof(sensor_disc_t)); + + g_sensor_disc.num++; + + // Sensor SEL Status + // Sensor# 0x5F + // EntitiyId# 0xD0, EntityInst# 0x02 + // Sensor Type# OEM: 0xC0 + // Event Read/Type# Sensor Specific: 0x6F + sensor.owner= BMC_SLAVE_ADDR; + sensor.lun = 0x00; + sensor.sensor_num = 0x5F; + + sensor.ent_id = 0xD0; + sensor.ent_inst = 0x02; + // Enable Scanning, Enable Events + sensor.sensor_init = 0x63; + // Supports Auto Re-Arm + sensor.sensor_caps = 0x40; + sensor.sensor_type = 0xC0; + sensor.evt_read_type = 0x6F; + // SEL Clear(bit1), SEL Rollover(bit8) + sensor.assert_evt_mask[0] = 0x02; + sensor.assert_evt_mask[1] = 0x01; + sensor.deassert_evt_mask[0] = 0x00; + sensor.deassert_evt_mask[1] = 0x00; + sensor.read_evt_mask[0] = 0x02; + sensor.read_evt_mask[1] = 0x01; + + // Device ID string + // Type - 0xC0: ASCII, Length - 12 + sensor.str_type_len = 0xC0 + 10; + strncpy(sensor.str, "SEL-Status", 10); + + // Add this sensor to the global table + if (g_sensor_disc.num >= SENSOR_DISC_MAX) { + syslog(LOG_ALERT, "populate_disc_sensors: num exceeded\n"); + return; + } + + memcpy(&g_sensor_disc.sensor[g_sensor_disc.num], &sensor, sizeof(sensor_disc_t)); + + g_sensor_disc.num++; + + + // Sensor WDT + // Sensor# 0x60 + // EntitiyId# 0xD0, EntityInst# 0x03 + // Sensor Type# WDT2: 0x23 + // Event Read/Type# Sensor Specific: 0x6F + sensor.owner= BMC_SLAVE_ADDR; + sensor.lun = 0x00; + sensor.sensor_num = 0x60; + + sensor.ent_id = 0xD0; + sensor.ent_inst = 0x03; + // Enable Scanning, Enable Events + sensor.sensor_init = 0x63; + // Supports Auto Re-Arm + sensor.sensor_caps = 0x40; + sensor.sensor_type = 0x23; + sensor.evt_read_type = 0x6F; + // 5 bits for expiry, reset, pwrdown, pwrcycle, timer + sensor.assert_evt_mask[0] = 0x0F; + sensor.assert_evt_mask[1] = 0x01; + sensor.deassert_evt_mask[0] = 0x00; + sensor.deassert_evt_mask[1] = 0x00; + sensor.read_evt_mask[0] = 0x0F; + sensor.read_evt_mask[1] = 0x01; + + // Device ID string + // Type - 0xC0: ASCII, Length - 12 + sensor.str_type_len = 0xC0 + 3; + strncpy(sensor.str, "WDT", 3); + + // Add this sensor to the global table + if (g_sensor_disc.num >= SENSOR_DISC_MAX) { + syslog(LOG_ALERT, "populate_disc_sensors: num exceeded\n"); + return; + } + + memcpy(&g_sensor_disc.sensor[g_sensor_disc.num], &sensor, sizeof(sensor_disc_t)); + + g_sensor_disc.num++; + + + // Sensor Chassis Pwr Sts + // Sensor# 0x70 + // EntitiyId# 0x15, EntityInst# 0x00 + // Sensor Type# OEM: 0xC8 + // Event Read/Type# Sensor Specific: 0x6F + sensor.owner= BMC_SLAVE_ADDR; + sensor.lun = 0x00; + sensor.sensor_num = 0x70; + + sensor.ent_id = 0x15; + sensor.ent_inst = 0x00; + // Enable Scanning, Enable Events + sensor.sensor_init = 0x63; + // Supports Auto Re-Arm + sensor.sensor_caps = 0x40; + sensor.sensor_type = 0xC8; + sensor.evt_read_type = 0x6F; + // 6 bits for pwroff, pwrcycle, pwron, softdown, ac-lost, hard-reset + sensor.assert_evt_mask[0] = 0x3F; + sensor.deassert_evt_mask[0] = 0x00; + sensor.read_evt_mask[0] = 0x3F; + + // Device ID string + // Type - 0xC0: ASCII, Length - 12 + sensor.str_type_len = 0xC0 + 13; + strncpy(sensor.str, "CH-Pwr-Status", 13); + + // Add this sensor to the global table + if (g_sensor_disc.num >= SENSOR_DISC_MAX) { + syslog(LOG_ALERT, "populate_disc_sensors: num exceeded\n"); + return; + } + + memcpy(&g_sensor_disc.sensor[g_sensor_disc.num], &sensor, sizeof(sensor_disc_t)); + + g_sensor_disc.num++; + + // Sensor CPU DIMM Hot + // Sensor# 0xB3 + // EntitiyId# 0xD0, EntityInst# 0x05 + // Sensor Type# OEM 0xC6 + // Event Read/Type# Sensor Specific 6Fh + sensor.owner= BMC_SLAVE_ADDR; + sensor.lun = 0x00; + sensor.sensor_num = 0xB3; + + sensor.ent_id = 0xD0; + sensor.ent_inst = 0x05; + // Enable Scanning, Enable Events + sensor.sensor_init = 0x63; + // Supports Auto Re-Arm + sensor.sensor_caps = 0x40; + sensor.sensor_type = 0xC6; + sensor.evt_read_type = 0x6F; + // Two bits for CPU Hot, DIMM Hot + sensor.assert_evt_mask[0] = 0x05; + sensor.deassert_evt_mask[0] = 0x05; + sensor.read_evt_mask[0] = 0x05; + + // Device ID string + // Type - 0xC0: ASCII, Length - 12 + sensor.str_type_len = 0xC0 + 12; + strncpy(sensor.str, "CPU_DIMM_HOT", 12); + + // Add this sensor to the global table + if (g_sensor_disc.num >= SENSOR_DISC_MAX) { + syslog(LOG_ALERT, "populate_disc_sensors: num exceeded\n"); + return; + } + + memcpy(&g_sensor_disc.sensor[g_sensor_disc.num], &sensor, sizeof(sensor_disc_t)); + + g_sensor_disc.num++; + + // Sensor PMBus Status Word Low + // Sensor PMBus Status Word High + // Sensor PMBus Status MFR + // Sensor PMBus Status Input + // Sensor NTP Status + // Sensor# 0xED + // EntitiyId# 0x35, EntityInst# 0x00 + // Sensor Type# OEM 0xC7 + // Event Read/Type# Sensor Specific 6Fh + sensor.owner= BMC_SLAVE_ADDR; + sensor.lun = 0x00; + sensor.sensor_num = 0xED; + + sensor.ent_id = 0x35; + sensor.ent_inst = 0x00; + // Enable Scanning, Enable Events + sensor.sensor_init = 0x63; + // Supports Auto Re-Arm + sensor.sensor_caps = 0x40; + sensor.sensor_type = 0xC7; + sensor.evt_read_type = 0x6F; + // 1-bit for date/time sync failed + sensor.assert_evt_mask[0] = 0x01; + sensor.deassert_evt_mask[0] = 0x00; + sensor.read_evt_mask[0] = 0x01; + + // Device ID string + // Type - 0xC0: ASCII, Length - 10 + sensor.str_type_len = 0xC0 + 12; + strncpy(sensor.str, "NTP-Status", 10); + + // Add this sensor to the global table + if (g_sensor_disc.num >= SENSOR_DISC_MAX) { + syslog(LOG_ALERT, "populate_disc_sensors: num exceeded\n"); + return; + } + + memcpy(&g_sensor_disc.sensor[g_sensor_disc.num], &sensor, sizeof(sensor_disc_t)); + + g_sensor_disc.num++; + + return; +} + +// Access functions for Sensor Table +void +plat_sensor_mgmt_info(int *p_num, sensor_mgmt_t **p_sensor) { + *p_num = g_sensor_mgmt.num; + *p_sensor = g_sensor_mgmt.sensor; +} + +void +plat_sensor_disc_info(int *p_num, sensor_disc_t **p_sensor) { + *p_num = g_sensor_disc.num; + *p_sensor = g_sensor_disc.sensor; +} + +void +plat_sensor_thresh_info(int *p_num, sensor_thresh_t **p_sensor) { + *p_num = g_sensor_thresh.num; + *p_sensor = g_sensor_thresh.sensor; +} + +void +plat_sensor_oem_info(int *p_num, sensor_oem_t **p_sensor) { + *p_num = g_sensor_oem.num; + *p_sensor = g_sensor_oem.sensor; +} + +// Initialize Sensor Table +int +plat_sensor_init(void) { + + // Populate all Sensors + populate_mgmt_sensors(); + populate_disc_sensors(); + + return 0; +} |