diff options
Diffstat (limited to 'common/recipes-lib/sdr')
-rw-r--r-- | common/recipes-lib/sdr/files/Makefile | 11 | ||||
-rw-r--r-- | common/recipes-lib/sdr/files/sdr.c | 210 | ||||
-rw-r--r-- | common/recipes-lib/sdr/files/sdr.h | 163 | ||||
-rw-r--r-- | common/recipes-lib/sdr/libsdr_0.1.bb | 30 |
4 files changed, 414 insertions, 0 deletions
diff --git a/common/recipes-lib/sdr/files/Makefile b/common/recipes-lib/sdr/files/Makefile new file mode 100644 index 0000000..11fe3ee --- /dev/null +++ b/common/recipes-lib/sdr/files/Makefile @@ -0,0 +1,11 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +lib: libsdr.so + +libsdr.so: sdr.c + $(CC) $(CFLAGS) -fPIC -c -o sdr.o sdr.c + $(CC) -lm -shared -o libsdr.so sdr.o -lc + +.PHONY: clean + +clean: + rm -rf *.o libsdr.so diff --git a/common/recipes-lib/sdr/files/sdr.c b/common/recipes-lib/sdr/files/sdr.c new file mode 100644 index 0000000..208b10f --- /dev/null +++ b/common/recipes-lib/sdr/files/sdr.c @@ -0,0 +1,210 @@ +/* + * + * 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 <stdlib.h> +#include <stdint.h> +#include <stdbool.h> +#include <math.h> +#include <fcntl.h> +#include <errno.h> +#include <syslog.h> +#include "sdr.h" + +#define FIELD_RATE_UNIT(x) ((x & (0x07 << 3)) >> 3) +#define FIELD_OP(x) ((x & (0x03 << 1)) >> 1) +#define FIELD_PERCENTAGE(x) (x & 0x01) + +#define FIELD_TYPE(x) ((x & (0x03 << 6)) >> 6) +#define FIELD_LEN(x) (x & 0xF) + +/* Array for BCD Plus definition. */ +const char bcd_plus_array[] = "0123456789 -.XXX"; + +/* Array for 6-Bit ASCII definition. */ +const char * ascii_6bit[4] = { + " !\"#$%&'()*+,-./", + "0123456789:;<=>?", + "@ABCDEFGHIJKLMNO", + "PQRSTUVWXYZ[\\]^_" +}; + +/* Get the units of the sensor from the SDR */ +int +sdr_get_sensor_units(sdr_full_t *sdr, uint8_t *op, uint8_t *modifier, + char *units) { + + uint8_t percent; + uint8_t rate_idx; + uint8_t base_idx; + + /* Bits 5:3 */ + rate_idx = FIELD_RATE_UNIT(sdr->sensor_units1); + + /* Bits 2:1 */ + *op = FIELD_OP(sdr->sensor_units1); + + /* Bit 0 */ + percent = FIELD_PERCENTAGE(sdr->sensor_units1); + + base_idx = sdr->sensor_units2; + + if (*op == 0x0 || *op == 0x3) + *modifier = 0; + else + *modifier = sdr->sensor_units3; + + if (percent) { + sprintf(units, "%"); + } else { + if (base_idx > 0 && base_idx <= MAX_SENSOR_BASE_UNIT) { + if (rate_idx > 0 && rate_idx < MAX_SENSOR_RATE_UNIT) { + sprintf(units, "%s %s", sensor_base_units[base_idx], + sensor_rate_units[rate_idx]); + } else { + sprintf(units, "%s", sensor_base_units[base_idx]); + } + } + } + + return 0; +} + + +/* Get the name of the sensor from the SDR */ +int +sdr_get_sensor_name(sdr_full_t *sdr, char *name) { + int field_type, field_len; + int idx, idx_eff, val; + char *str; + + /* Bits 7:6 */ + field_type = FIELD_TYPE(sdr->str_type_len); + /* Bits 4:0 */ + field_len = FIELD_LEN(sdr->str_type_len) + 1; + + str = sdr->str; + + /* Case: length is zero */ + if (field_len == 1) { + syslog(LOG_ALERT, "get_sensor_name: str length is 0\n"); + // TODO: Fix this hack later + sprintf(name, "%s", str); + return -1; + } + + /* Retrieve field data depending on the type it was stored. */ + switch (field_type) { + case TYPE_BINARY: + /* TODO: Need to add support to read data stored in binary type. */ + break; + + case TYPE_BCD_PLUS: + + idx = 0; + while (idx != field_len) { + name[idx] = bcd_plus_array[str[idx] & 0x0F]; + idx++; + } + name[idx] = '\0'; + break; + + case TYPE_ASCII_6BIT: + + idx_eff = idx = 0; + + while (field_len > 0) { + + /* 6-Bits => Bits 5:0 of the first byte */ + val = str[idx] & 0x3F; + name[idx_eff++] = ascii_6bit[(val & 0xF0) >> 4][val & 0x0F]; + field_len--; + + if (field_len > 0) { + /* 6-Bits => Bits 3:0 of second byte + Bits 7:6 of first byte. */ + val = ((str[idx] & 0xC0) >> 6) | + ((str[idx + 1] & 0x0F) << 2); + name[idx_eff++] = ascii_6bit[(val & 0xF0) >> 4][val & 0x0F]; + field_len--; + } + + if (field_len > 0) { + /* 6-Bits => Bits 1:0 of third byte + Bits 7:4 of second byte. */ + val = ((str[idx + 1] & 0xF0) >> 4) | + ((str[idx + 2] & 0x03) << 4); + name[idx_eff++] = ascii_6bit[(val & 0xF0) >> 4][val & 0x0F]; + + /* 6-Bits => Bits 7:2 of third byte. */ + val = ((str[idx + 2] & 0xFC) >> 2); + name[idx_eff++] = ascii_6bit[(val & 0xF0) >> 4][val & 0x0F]; + + field_len--; + idx += 3; + } + } + /* Add Null terminator */ + name[idx_eff] = '\0'; + break; + + case TYPE_ASCII_8BIT: + snprintf(name, field_len, str); + /* Add Null terminator */ + name[field_len] = '\0'; + break; + } + + return 0; +} + +/* Populates all sensor_info_t struct using the path to SDR dump */ +int +sdr_init(char *path, sensor_info_t *sinfo) { + int fd; + uint8_t buf[MAX_SDR_LEN] = {0}; + uint8_t bytes_rd = 0; + uint8_t snr_num = 0; + sdr_full_t *sdr; + + while (access(path, F_OK) == -1) { + sleep(5); + } + + fd = open(path, O_RDONLY); + if (fd < 0) { + syslog(LOG_ERR, "sdr_init: open failed for %s\n", path); + return -1; + } + + while ((bytes_rd = read(fd, buf, sizeof(sdr_full_t))) > 0) { + if (bytes_rd != sizeof(sdr_full_t)) { + syslog(LOG_ERR, "sdr_init: read returns %d bytes\n", bytes_rd); + return -1; + } + + sdr = (sdr_full_t *) buf; + snr_num = sdr->sensor_num; + sinfo[snr_num].valid = true; + memcpy(&sinfo[snr_num].sdr, sdr, sizeof(sdr_full_t)); + } + + return 0; +} + diff --git a/common/recipes-lib/sdr/files/sdr.h b/common/recipes-lib/sdr/files/sdr.h new file mode 100644 index 0000000..c474fb1 --- /dev/null +++ b/common/recipes-lib/sdr/files/sdr.h @@ -0,0 +1,163 @@ +/* + * + * 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 __SDR_H__ +#define __SDR_H__ + +#include <stdbool.h> +#include <openbmc/ipmi.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#define MAX_SDR_LEN 64 + + +#define MAX_SENSOR_RATE_UNIT 7 +#define MAX_SENSOR_BASE_UNIT 92 + +typedef struct _sensor_info_t { + bool valid; + sdr_full_t sdr; +} sensor_info_t; + +/* List of all the Sensor Rate Units types. */ +const char * sensor_rate_units[] = { + "", /* 0x00 */ + "per \xC2\xB5s", /* 0x01 */ + "per ms", /* 0x02 */ + "per s", /* 0x03 */ + "per min", /* 0x04 */ + "per hour", /* 0x05 */ + "per day", /* 0x06 */ + "reserved", /* 0x07 */ +}; + + +/* List of all the Sensor Base Units types. */ +const char * sensor_base_units[] = { + "", /* 000 */ + "C", /* 001 */ + "F", /* 002 */ + "K", /* 003 */ + "Volts", /* 004 */ + "Amps", /* 005 */ + "Watts", /* 006 */ + "Joules", /* 007 */ + "Coulombs", /* 008 */ + "VA", /* 009 */ + "Nits", /* 010 */ + "lumen", /* 011 */ + "lux", /* 012 */ + "Candela", /* 013 */ + "kPa", /* 014 */ + "PSI", /* 015 */ + "Newton", /* 016 */ + "CFM", /* 017 */ + "RPM", /* 018 */ + "Hz", /* 019 */ + "\xC2\xB5s", /* 020 */ + "ms", /* 021 */ + "sec", /* 022 */ + "min", /* 023 */ + "hour", /* 024 */ + "day", /* 025 */ + "week", /* 026 */ + "mil", /* 027 */ + "inches", /* 028 */ + "feet", /* 029 */ + "cu in", /* 030 */ + "cu feet", /* 031 */ + "mm", /* 032 */ + "cm", /* 033 */ + "m", /* 034 */ + "cu cm", /* 035 */ + "cu m", /* 036 */ + "liters", /* 037 */ + "fluid ounce", /* 038 */ + "radians", /* 039 */ + "steradians", /* 040 */ + "revolutions", /* 041 */ + "cycles", /* 042 */ + "gravities", /* 043 */ + "ounce", /* 044 */ + "pound", /* 045 */ + "ft-lb", /* 046 */ + "oz-in", /* 047 */ + "gauss", /* 048 */ + "gilberts", /* 049 */ + "henry", /* 050 */ + "millihenry", /* 051 */ + "farad", /* 052 */ + "microfarad", /* 053 */ + "ohms", /* 054 */ + "siemens", /* 055 */ + "mole", /* 056 */ + "becquerel", /* 057 */ + "PPM", /* 058 */ + "reserved", /* 059 */ + "Db", /* 060 */ + "DbA", /* 061 */ + "DbC", /* 062 */ + "gray", /* 063 */ + "sievert", /* 064 */ + "color temp deg K", /* 065 */ + "bit", /* 066 */ + "kilobit", /* 067 */ + "megabit", /* 068 */ + "gigabit", /* 069 */ + "B", /* 070 */ + "KB", /* 071 */ + "MB", /* 072 */ + "GB", /* 073 */ + "word", /* 074 */ + "dword", /* 075 */ + "qword", /* 076 */ + "line", /* 077 */ + "hit", /* 078 */ + "miss", /* 079 */ + "retry", /* 080 */ + "reset", /* 081 */ + "overflow", /* 082 */ + "underrun", /* 083 */ + "collision", /* 084 */ + "packets", /* 085 */ + "messages", /* 086 */ + "characters", /* 087 */ + "error", /* 088 */ + "correctable error", /* 089 */ + "uncorrectable error", /* 090 */ + "fatal error", /* 091 */ + "grams", /* 092 */ + "", /* 093 */ +}; + +int sdr_init(char *path, sensor_info_t *sinfo); + +int sdr_get_sensor_units(sdr_full_t *sdr, uint8_t *op, uint8_t *modifier, + char *units); +int sdr_get_sensor_name(sdr_full_t *sdr, char *name); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* __SDR_H__ */ diff --git a/common/recipes-lib/sdr/libsdr_0.1.bb b/common/recipes-lib/sdr/libsdr_0.1.bb new file mode 100644 index 0000000..958e0c6 --- /dev/null +++ b/common/recipes-lib/sdr/libsdr_0.1.bb @@ -0,0 +1,30 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +SUMMARY = "SDR Library" +DESCRIPTION = "library for extracting information from SDR" +SECTION = "base" +PR = "r1" +LICENSE = "GPLv2" + + +LIC_FILES_CHKSUM = "file://sdr.c;beginline=8;endline=20;md5=da35978751a9d71b73679307c4d296ec" + + +SRC_URI = "file://Makefile \ + file://sdr.c \ + file://sdr.h \ + " + +S = "${WORKDIR}" + +DEPENDS += " libipmi " + +do_install() { + install -d ${D}${libdir} + install -m 0644 libsdr.so ${D}${libdir}/libsdr.so + + install -d ${D}${includedir}/openbmc + install -m 0644 sdr.h ${D}${includedir}/openbmc/sdr.h +} + +FILES_${PN} = "${libdir}/libsdr.so" +FILES_${PN}-dev = "${includedir}/openbmc/sdr.h" |