diff options
Diffstat (limited to 'common/recipes-lib')
22 files changed, 2464 insertions, 0 deletions
diff --git a/common/recipes-lib/fruid/files/Makefile b/common/recipes-lib/fruid/files/Makefile new file mode 100644 index 0000000..225d5f7 --- /dev/null +++ b/common/recipes-lib/fruid/files/Makefile @@ -0,0 +1,27 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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 in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA + +lib: libfruid.so + +libfruid.so: fruid.c + $(CC) $(CFLAGS) -fPIC -c -o fruid.o fruid.c + $(CC) -shared -o libfruid.so fruid.o -lc + +.PHONY: clean + +clean: + rm -rf *.o libfruid.so diff --git a/common/recipes-lib/fruid/files/fruid.c b/common/recipes-lib/fruid/files/fruid.c new file mode 100644 index 0000000..dc71ac8 --- /dev/null +++ b/common/recipes-lib/fruid/files/fruid.c @@ -0,0 +1,682 @@ +/* + * 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. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <string.h> +#include <syslog.h> +#include <time.h> +#include "fruid.h" + +#define FIELD_TYPE(x) ((x & (0x03 << 6)) >> 6) +#define FIELD_LEN(x) (x & ~(0x03 << 6)) +#define FIELD_EMPTY "N/A" + +/* Unix time difference between 1970 and 1996. */ +#define UNIX_TIMESTAMP_1996 820454400 + +/* 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[\\]^_" +}; + +/* + * calculate_time - calculate time from the unix time stamp stored + * + * @mfg_time : Unix timestamp since 1996 + * + * returns char * for mfg_time_str + * returns NULL for memory allocation failure + */ +static char * calculate_time(uint8_t * mfg_time) +{ + int len; + struct tm * local; + time_t unix_time = 0; + unix_time = ((mfg_time[2] << 16) + (mfg_time[1] << 8) + mfg_time[0]) * 60; + unix_time += UNIX_TIMESTAMP_1996; + + local = localtime(&unix_time); + char * str = asctime(local); + + len = strlen(str); + + char * mfg_time_str = (char *) malloc(len); + if (!mfg_time_str) { + syslog(LOG_ALERT, "fruid: malloc: memory allocation failed\n"); + return NULL; + } + + memset(mfg_time_str, 0, len); + + memcpy(mfg_time_str, str, len); + + mfg_time_str[len - 1] = '\0'; + + return mfg_time_str; +} + +/* + * verify_chksum - verify the zero checksum of the data + * + * @area : offset of the area + * @len : len of the area in bytes + * @chksum_read : stored checksum in the data. + * + * returns 0 if chksum is verified + * returns -1 if there exist a mismatch + */ +static int verify_chksum(uint8_t * area, uint8_t len, uint8_t chksum_read) +{ + int i; + uint8_t chksum = 0; + + for (i = 0; i < len - 1; i++) + chksum += area[i]; + + /* Zero checksum calculation */ + chksum = ~(chksum) + 1; + + return (chksum == chksum_read) ? 0 : -1; +} + +/* + * get_chassis_type - get the Chassis type + * + * @type_hex : type stored in the data + * + * returns char ptr for chassis type string + * returns NULL if type not in the list + */ +static char * get_chassis_type(uint8_t type_hex) +{ + int type, ret; + char type_int[4]; + + ret = sprintf(type_int, "%u", type_hex); + type = atoi(type_int) - 1; + + /* If the type is not in the list defined.*/ + if (type > FRUID_CHASSIS_TYPECODE_MAX || type < FRUID_CHASSIS_TYPECODE_MIN) { + syslog(LOG_INFO, "fruid: chassis area: invalid chassis type\n"); + return NULL; + } + + char * type_str = (char *) malloc(strlen(fruid_chassis_type[type])); + if (!type_str) { + syslog(LOG_ALERT, "fruid: malloc: memory allocation failed\n"); + return NULL; + } + + memcpy(type_str, fruid_chassis_type[type], strlen(fruid_chassis_type[type])); + + return type_str; +} + +/* + * _fruid_area_field_read - read the field data + * + * @offset : offset of the field + * + * returns char ptr for the field data string + */ +static char * _fruid_area_field_read(uint8_t *offset) +{ + int field_type, field_len, field_len_eff; + int idx, idx_eff, val; + char * field; + + /* Bits 7:6 */ + field_type = FIELD_TYPE(offset[0]); + /* Bits 5:0 */ + field_len = FIELD_LEN(offset[0]); + + /* Calculate the effective length of the field data based on type stored. */ + switch (field_type) { + + case TYPE_BINARY: + /* TODO: Need to add support to read data stored in binary type. */ + field_len_eff = 1; + break; + + case TYPE_ASCII_6BIT: + /* + * Every 3 bytes have four 6-bit packed values + * + 6-bit values from the remaining field bytes. + */ + field_len_eff = (field_len / 3) * 4 + (field_len % 3); + break; + + case TYPE_BCD_PLUS: + case TYPE_ASCII_8BIT: + field_len_eff = field_len; + break; + } + + /* If field data is zero, store 'N/A' for that field. */ + field_len_eff > 0 ? (field = (char *) malloc(field_len_eff + 1)) : + (field = (char *) malloc(strlen(FIELD_EMPTY))); + if (!field) { + syslog(LOG_ALERT, "fruid: malloc: memory allocation failed\n"); + return NULL; + } + + memset(field, 0, field_len + 1); + + if (field_len_eff < 1) { + strcpy(field, FIELD_EMPTY); + return field; + } + + /* 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) { + field[idx] = bcd_plus_array[offset[idx + 1] & 0x0F]; + idx++; + } + field[idx] = '\0'; + break; + + case TYPE_ASCII_6BIT: + + idx_eff = 0, idx = 1; + + while (field_len > 0) { + + /* 6-Bits => Bits 5:0 of the first byte */ + val = offset[idx] & 0x3F; + field[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 = ((offset[idx] & 0xC0) >> 6) | + ((offset[idx + 1] & 0x0F) << 2); + field[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 = ((offset[idx + 1] & 0xF0) >> 4) | + ((offset[idx + 2] & 0x03) << 4); + field[idx_eff++] = ascii_6bit[(val & 0xF0) >> 4][val & 0x0F]; + + /* 6-Bits => Bits 7:2 of third byte. */ + val = ((offset[idx + 2] & 0xFC) >> 2); + field[idx_eff++] = ascii_6bit[(val & 0xF0) >> 4][val & 0x0F]; + + field_len--; + idx += 3; + } + } + /* Add Null terminator */ + field[idx_eff] = '\0'; + break; + + case TYPE_ASCII_8BIT: + + memcpy(field, offset + 1, field_len); + /* Add Null terminator */ + field[field_len] = '\0'; + break; + } + + return field; +} + +/* Free all the memory allocated for fruid information */ +void free_fruid_info(fruid_info_t * fruid) +{ + if (fruid->chassis.flag) { + free(fruid->chassis.type_str); + free(fruid->chassis.part); + free(fruid->chassis.serial); + free(fruid->chassis.custom); + } + + if (fruid->board.flag) { + free(fruid->board.mfg_time_str); + free(fruid->board.mfg); + free(fruid->board.name); + free(fruid->board.serial); + free(fruid->board.part); + free(fruid->board.fruid); + } + + if (fruid->product.flag) { + free(fruid->board.custom); + free(fruid->product.mfg); + free(fruid->product.name); + free(fruid->product.part); + free(fruid->product.version); + free(fruid->product.serial); + free(fruid->product.asset_tag); + free(fruid->product.fruid); + free(fruid->product.custom); + } +} + +/* Initialize the fruid information struct */ +static void init_fruid_info(fruid_info_t * fruid) +{ + fruid->chassis.flag = 0; + fruid->board.flag = 0; + fruid->product.flag = 0; + fruid->chassis.type_str = NULL; + fruid->chassis.part = NULL; + fruid->chassis.serial = NULL; + fruid->chassis.custom = NULL; + fruid->board.mfg_time_str = NULL; + fruid->board.mfg = NULL; + fruid->board.name = NULL; + fruid->board.serial = NULL; + fruid->board.part = NULL; + fruid->board.fruid = NULL; + fruid->board.custom = NULL; + fruid->product.mfg = NULL; + fruid->product.name = NULL; + fruid->product.part = NULL; + fruid->product.version = NULL; + fruid->product.serial = NULL; + fruid->product.asset_tag = NULL; + fruid->product.fruid = NULL; + fruid->product.custom = NULL; +} + +/* Parse the Product area data */ +int parse_fruid_area_product(uint8_t * product, + fruid_area_product_t * fruid_product) +{ + int ret, index; + + index = 0; + + /* Reset the struct to zero */ + memset(fruid_product, 0, sizeof(fruid_area_product_t)); + + /* Check if the format version is as per IPMI FRUID v1.0 format spec */ + fruid_product->format_ver = product[index++]; + if (fruid_product->format_ver != FRUID_FORMAT_VER) { + syslog(LOG_ERR, "fruid: product_area: format version not supported"); + return EPROTONOSUPPORT; + } + + fruid_product->area_len = product[index++] * FRUID_AREA_LEN_MULTIPLIER; + fruid_product->lang_code = product[index++]; + + fruid_product->chksum = product[fruid_product->area_len - 1]; + ret = verify_chksum((uint8_t *) product, + fruid_product->area_len, fruid_product->chksum); + + if (ret) { + syslog(LOG_ERR, "fruid: product_area: chksum not verified."); + return EBADF; + } + + fruid_product->mfg = _fruid_area_field_read(&product[index]); + if (fruid_product->mfg == NULL) + return ENOMEM; + index += FIELD_LEN(product[index]) + 1; + + fruid_product->name = _fruid_area_field_read(&product[index]); + if (fruid_product->name == NULL) + return ENOMEM; + index += FIELD_LEN(product[index]) + 1; + + fruid_product->part = _fruid_area_field_read(&product[index]); + if (fruid_product->part == NULL) + return ENOMEM; + index += FIELD_LEN(product[index]) + 1; + + fruid_product->version = _fruid_area_field_read(&product[index]); + if (fruid_product->version == NULL) + return ENOMEM; + index += FIELD_LEN(product[index]) + 1; + + fruid_product->serial = _fruid_area_field_read(&product[index]); + if (fruid_product->serial == NULL) + return ENOMEM; + index += FIELD_LEN(product[index]) + 1; + + fruid_product->asset_tag = _fruid_area_field_read(&product[index]); + if (fruid_product->asset_tag == NULL) + return ENOMEM; + index += FIELD_LEN(product[index]) + 1; + + fruid_product->fruid = _fruid_area_field_read(&product[index]); + if (fruid_product->fruid == NULL) + return ENOMEM; + index += FIELD_LEN(product[index]) + 1; + + fruid_product->custom = _fruid_area_field_read(&product[index]); + if (fruid_product->custom == NULL) + return ENOMEM; + index += FIELD_LEN(product[index]) + 1; + + return 0; +} + +/* Parse the Board area data */ +int parse_fruid_area_board(uint8_t * board, + fruid_area_board_t * fruid_board) +{ + int ret, index, i; + time_t unix_time; + + index = 0; + + /* Reset the struct to zero */ + memset(fruid_board, 0, sizeof(fruid_area_board_t)); + + /* Check if the format version is as per IPMI FRUID v1.0 format spec */ + fruid_board->format_ver = board[index++]; + if (fruid_board->format_ver != FRUID_FORMAT_VER) { + syslog(LOG_ERR, "fruid: board_area: format version not supported"); + return EPROTONOSUPPORT; + } + fruid_board->area_len = board[index++] * FRUID_AREA_LEN_MULTIPLIER; + fruid_board->lang_code = board[index++]; + + fruid_board->chksum = board[fruid_board->area_len - 1]; + ret = verify_chksum((uint8_t *) board, + fruid_board->area_len, fruid_board->chksum); + + if (ret) { + syslog(LOG_ERR, "fruid: board_area: chksum not verified."); + return EBADF; + } + + for (i = 0; i < 3; i++) { + fruid_board->mfg_time[i] = board[index++]; + } + + fruid_board->mfg_time_str = calculate_time(fruid_board->mfg_time); + if (fruid_board->mfg_time_str == NULL) + return ENOMEM; + + fruid_board->mfg = _fruid_area_field_read(&board[index]); + if (fruid_board->mfg == NULL) + return ENOMEM; + index += FIELD_LEN(board[index]) + 1; + + fruid_board->name = _fruid_area_field_read(&board[index]); + if (fruid_board->name == NULL) + return ENOMEM; + index += FIELD_LEN(board[index]) + 1; + + fruid_board->serial = _fruid_area_field_read(&board[index]); + if (fruid_board->serial == NULL) + return ENOMEM; + index += FIELD_LEN(board[index]) + 1; + + fruid_board->part = _fruid_area_field_read(&board[index]); + if (fruid_board->part == NULL) + return ENOMEM; + index += FIELD_LEN(board[index]) + 1; + + fruid_board->fruid = _fruid_area_field_read(&board[index]); + if (fruid_board->fruid == NULL) + return ENOMEM; + index += FIELD_LEN(board[index]) + 1; + + fruid_board->custom = _fruid_area_field_read(&board[index]); + if (fruid_board->custom == NULL) + return ENOMEM; + index += FIELD_LEN(board[index]) + 1; + + return 0; +} + +/* Parse the Chassis area data */ +int parse_fruid_area_chassis(uint8_t * chassis, + fruid_area_chassis_t * fruid_chassis) +{ + int ret, index; + + index = 0; + + /* Reset the struct to zero */ + memset(fruid_chassis, 0, sizeof(fruid_area_chassis_t)); + + /* Check if the format version is as per IPMI FRUID v1.0 format spec */ + fruid_chassis->format_ver = chassis[index++]; + if (fruid_chassis->format_ver != FRUID_FORMAT_VER) { + syslog(LOG_ERR, "fruid: chassis_area: format version not supported"); + return EPROTONOSUPPORT; + } + + fruid_chassis->area_len = chassis[index++] * FRUID_AREA_LEN_MULTIPLIER; + fruid_chassis->type = chassis[index++]; + + fruid_chassis->chksum = chassis[fruid_chassis->area_len - 1]; + ret = verify_chksum((uint8_t *) chassis, + fruid_chassis->area_len, fruid_chassis->chksum); + if (ret) { + syslog(LOG_ERR, "fruid: chassis_area: chksum not verified."); + return EBADF; + } + + fruid_chassis->type_str = get_chassis_type(fruid_chassis->type); + if (fruid_chassis->type_str == NULL) + return ENOMSG; + + fruid_chassis->part = _fruid_area_field_read(&chassis[index]); + if (fruid_chassis->part == NULL) + return ENOMEM; + index += FIELD_LEN(chassis[index]) + 1; + + fruid_chassis->serial = _fruid_area_field_read(&chassis[index]); + if (fruid_chassis->serial == NULL) + return ENOMEM; + index += FIELD_LEN(chassis[index]) + 1; + + fruid_chassis->custom = _fruid_area_field_read(&chassis[index]); + if (fruid_chassis->custom == NULL) + return ENOMEM; + index += FIELD_LEN(chassis[index]) + 1; + + return 0; +} + +/* Calculate the area offsets and populate the fruid_eeprom_t struct */ +void set_fruid_eeprom_offsets(uint8_t * eeprom, fruid_header_t * header, + fruid_eeprom_t * fruid_eeprom) +{ + fruid_eeprom->header = eeprom + 0x00; + + header->offset_area.chassis ? (fruid_eeprom->chassis = eeprom + \ + (header->offset_area.chassis * FRUID_OFFSET_MULTIPLIER)) : \ + (fruid_eeprom->chassis = NULL); + + header->offset_area.board ? (fruid_eeprom->board = eeprom + \ + (header->offset_area.board * FRUID_OFFSET_MULTIPLIER)) : \ + (fruid_eeprom->board = NULL); + + header->offset_area.product ? (fruid_eeprom->product = eeprom + \ + (header->offset_area.product * FRUID_OFFSET_MULTIPLIER)) : \ + (fruid_eeprom->product = NULL); + + header->offset_area.multirecord ? (fruid_eeprom->multirecord = eeprom + \ + (header->offset_area.multirecord * FRUID_OFFSET_MULTIPLIER)) : \ + (fruid_eeprom->multirecord = NULL); +} + +/* Populate the common header struct */ +int parse_fruid_header(uint8_t * eeprom, fruid_header_t * header) +{ + int ret; + + memcpy((uint8_t *)header, (uint8_t *)eeprom, sizeof(fruid_header_t)); + ret = verify_chksum((uint8_t *) header, + sizeof(fruid_header_t), header->chksum); + if (ret) { + syslog(LOG_ERR, "fruid: common_header: chksum not verified."); + return EBADF; + } + + return ret; +} + +/* Parse the eeprom dump and populate the fruid info in struct */ +int populate_fruid_info(fruid_eeprom_t * fruid_eeprom, fruid_info_t * fruid) +{ + int ret; + + /* Initial all the required fruid structures */ + fruid_area_chassis_t fruid_chassis; + fruid_area_board_t fruid_board; + fruid_area_product_t fruid_product; + + /* If Chassis area is present, parse and print it */ + if (fruid_eeprom->chassis) { + ret = parse_fruid_area_chassis(fruid_eeprom->chassis, &fruid_chassis); + if (!ret) { + fruid->chassis.flag = 1; + fruid->chassis.type_str = fruid_chassis.type_str; + fruid->chassis.part = fruid_chassis.part; + fruid->chassis.serial = fruid_chassis.serial; + fruid->chassis.custom = fruid_chassis.custom; + } else + return ret; + } + + /* If Board area is present, parse and print it */ + if (fruid_eeprom->board) { + ret = parse_fruid_area_board(fruid_eeprom->board, &fruid_board); + if (!ret) { + fruid->board.flag = 1; + fruid->board.mfg_time_str = fruid_board.mfg_time_str; + fruid->board.mfg = fruid_board.mfg; + fruid->board.name = fruid_board.name; + fruid->board.serial = fruid_board.serial; + fruid->board.part = fruid_board.part; + fruid->board.fruid = fruid_board.fruid; + fruid->board.custom = fruid_board.custom; + } else + return ret; + } + + /* If Product area is present, parse and print it */ + if (fruid_eeprom->product) { + ret = parse_fruid_area_product(fruid_eeprom->product, &fruid_product); + if (!ret) { + fruid->product.flag = 1; + fruid->product.mfg = fruid_product.mfg; + fruid->product.name = fruid_product.name; + fruid->product.part = fruid_product.part; + fruid->product.version = fruid_product.version; + fruid->product.serial = fruid_product.serial; + fruid->product.asset_tag = fruid_product.asset_tag; + fruid->product.fruid = fruid_product.fruid; + fruid->product.custom = fruid_product.custom; + } else + return ret; + } + + return 0; +} + +/* + * fruid_parse - To parse the bin file (eeprom) and populate + * the fruid information in the struct + * @bin : Eeprom binary file + * @fruid : ptr to the struct that holds the fruid information + * + * returns 0 on success + * returns non-zero errno value on error + */ +int fruid_parse(const char * bin, fruid_info_t * fruid) +{ + int fruid_len, ret; + FILE *fruid_fd; + uint8_t * eeprom; + + /* Initial all the required fruid structures */ + fruid_header_t fruid_header; + fruid_eeprom_t fruid_eeprom; + + memset(&fruid_header, 0, sizeof(fruid_header_t)); + memset(&fruid_eeprom, 0, sizeof(fruid_eeprom_t)); + + /* Reset parser return value */ + ret = 0; + + /* Open the FRUID binary file */ + fruid_fd = fopen(bin, "rb"); + if (!fruid_fd) { + syslog(LOG_ERR, "fruid: unable to open the file"); + return ENOENT; + } + + /* Get the size of the binary file */ + fseek(fruid_fd, 0, SEEK_END); + fruid_len = (uint32_t) ftell(fruid_fd); + + fseek(fruid_fd, 0, SEEK_SET); + + eeprom = (uint8_t *) malloc(fruid_len); + if (!eeprom) { + syslog(LOG_ALERT, "fruid: malloc: memory allocation failed\n"); + return ENOMEM; + } + + /* Read the binary file */ + fread(eeprom, sizeof(uint8_t), fruid_len, fruid_fd); + + /* Close the FRUID binary file */ + fclose(fruid_fd); + + /* Parse the common header data */ + ret = parse_fruid_header(eeprom, &fruid_header); + if (ret) { + /* Free the eeprom malloc'ed memory */ + free(eeprom); + return ret; + } + + /* Calculate all the area offsets */ + set_fruid_eeprom_offsets(eeprom, &fruid_header, &fruid_eeprom); + + init_fruid_info(fruid); + /* Parse the eeprom and populate the fruid information */ + ret = populate_fruid_info(&fruid_eeprom, fruid); + if (ret) { + /* Free the malloced memory for the fruid information */ + free_fruid_info(fruid); + } + + /* Free the eeprom malloced memory */ + free(eeprom); + + return ret; +} diff --git a/common/recipes-lib/fruid/files/fruid.h b/common/recipes-lib/fruid/files/fruid.h new file mode 100644 index 0000000..713658d --- /dev/null +++ b/common/recipes-lib/fruid/files/fruid.h @@ -0,0 +1,192 @@ +/* + * 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__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdlib.h> +#include <stdint.h> +#include <openbmc/ipmi.h> + +#define FRUID_FORMAT_VER 0x01 +#define FRUID_OFFSET_MULTIPLIER 8 +#define FRUID_AREA_LEN_MULTIPLIER 8 + +#define FRUID_OFFSET_AREA_INTERNAL 0 +#define FRUID_OFFSET_AREA_CHASSIS 1 +#define FRUID_OFFSET_AREA_BOARD 2 +#define FRUID_OFFSET_AREA_PRODUCT 3 +#define FRUID_OFFSET_AREA_MULTIRECORD 4 + +#define FRUID_CHASSIS_TYPECODE_MIN 1 +#define FRUID_CHASSIS_TYPECODE_MAX 32 + +/* To hold the common header information. */ +typedef struct fruid_header_t { + uint8_t format_ver : 4; + struct { + uint8_t internal; + uint8_t chassis; + uint8_t board; + uint8_t product; + uint8_t multirecord; + } offset_area; + uint8_t pad; + uint8_t chksum; +} fruid_header_t; + +/* To hold the Chassis area information. */ +typedef struct fruid_area_chassis_t { + uint8_t format_ver : 4; + uint8_t area_len; + uint8_t type; + char * type_str; + char * part; + char * serial; + char * custom; + uint8_t chksum; +} fruid_area_chassis_t; + +/* To hold the Board area information. */ +typedef struct fruid_area_board_t { + uint8_t format_ver : 4; + uint8_t area_len; + uint8_t lang_code; + uint8_t mfg_time[3]; + char * mfg_time_str; + char * mfg; + char * name; + char * serial; + char * part; + char * fruid; + char * custom; + uint8_t chksum; +} fruid_area_board_t; + +/* To hold the Product area information. */ +typedef struct fruid_area_product_t { + uint8_t format_ver : 4; + uint8_t area_len; + uint8_t lang_code; + char * mfg; + char * name; + char * part; + char * version; + char * serial; + char * asset_tag; + char * fruid; + char * custom; + uint8_t chksum; +} fruid_area_product_t; + +/* To hold the Multirecord area information. */ +typedef struct fruid_area_multirecord_t { + uint8_t format_ver : 4; + uint8_t area_len; + /* TODO: Add more fields to support Multirecord area. */ +} fruid_area_multirecord_t; + +/* To hold all the fruid information */ +typedef struct fruid_info_t { + struct { + uint8_t flag; + char * type_str; + char * part; + char * serial; + char * custom; + } chassis; + struct { + uint8_t flag; + char * mfg_time_str; + char * mfg; + char * name; + char * serial; + char * part; + char * fruid; + char * custom; + } board; + struct { + uint8_t flag; + char * mfg; + char * name; + char * part; + char * version; + char * serial; + char * asset_tag; + char * fruid; + char * custom; + } product; +} fruid_info_t; + +/* To hold the different area offsets. */ +typedef struct fruid_eeprom_t { + uint8_t * header; + uint8_t * chassis; + uint8_t * board; + uint8_t * product; + uint8_t * multirecord; +} fruid_eeprom_t; + +/* List of all the Chassis types. */ +const char * fruid_chassis_type [] = { + "Other", /* 0x01 */ + "Unknown", /* 0x02 */ + "Desktop", /* 0x03 */ + "Low Profile Desktop", /* 0x04 */ + "Pizza Box", /* 0x05 */ + "Mini Tower", /* 0x06 */ + "Tower", /* 0x07 */ + "Portable", /* 0x08 */ + "Laptop", /* 0x09 */ + "Notebook", /* 0x0A */ + "Hand Held", /* 0x0B */ + "Docking Station", /* 0x0C */ + "All in One", /* 0x0D */ + "Sub Notebook", /* 0x0E */ + "Space-saving", /* 0x0F */ + "Lunch Box", /* 0x10 */ + "Main Server Chassis", /* 0x11 */ + "Expansion Chassis", /* 0x12 */ + "SubChassis", /* 0x13 */ + "Bus Expansion Chassis", /* 0x14 */ + "Peripheral Chassis", /* 0x15 */ + "RAID Chassis", /* 0x16 */ + "Rack Mount Chassis", /* 0x17 */ + "Sealed-case PC", /* 0x18 */ + "Multi-system Chassis", /* 0x19 */ + "Compact PCI", /* 0x1A */ + "Advanced TCA", /* 0x1B */ + "Blade", /* 0x1C */ + "Blade Enclosure", /* 0x1D */ + "Tablet", /* 0x1E */ + "Convertible", /* 0x1F */ + "Detachable" /* 0x20 */ +}; + +int fruid_parse(const char * bin, fruid_info_t * fruid); +void free_fruid_info(fruid_info_t * fruid); + +#ifdef __cplusplus +} +#endif + +#endif /* __FRUID_H__ */ diff --git a/common/recipes-lib/fruid/libfruid_0.1.bb b/common/recipes-lib/fruid/libfruid_0.1.bb new file mode 100644 index 0000000..7984d3b --- /dev/null +++ b/common/recipes-lib/fruid/libfruid_0.1.bb @@ -0,0 +1,43 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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 in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA + +SUMMARY = "IPMI FRUID Library" +DESCRIPTION = "library for ipmi fruid" +SECTION = "base" +PR = "r1" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://fruid.c;beginline=4;endline=16;md5=da35978751a9d71b73679307c4d296ec" + +SRC_URI = "file://Makefile \ + file://fruid.c \ + file://fruid.h \ + " + +S = "${WORKDIR}" + +DEPENDS += " libipmi " + +do_install() { + install -d ${D}${libdir} + install -m 0644 libfruid.so ${D}${libdir}/libfruid.so + + install -d ${D}${includedir}/openbmc + install -m 0644 fruid.h ${D}${includedir}/openbmc/fruid.h +} + +FILES_${PN} = "${libdir}/libfruid.so" +FILES_${PN}-dev = "${includedir}/openbmc/fruid.h" diff --git a/common/recipes-lib/gpio/files/src/Makefile b/common/recipes-lib/gpio/files/src/Makefile new file mode 100644 index 0000000..0b605fc --- /dev/null +++ b/common/recipes-lib/gpio/files/src/Makefile @@ -0,0 +1,27 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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 in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA + +lib: libgpio.so + +libgpio.so: gpio.c + $(CC) $(CFLAGS) -fPIC -c -o gpio.o gpio.c + $(CC) -shared -o libgpio.so gpio.o -lc + +.PHONY: clean + +clean: + rm -rf *.o libgpio.so diff --git a/common/recipes-lib/gpio/files/src/gpio.c b/common/recipes-lib/gpio/files/src/gpio.c new file mode 100644 index 0000000..9c1f7a2 --- /dev/null +++ b/common/recipes-lib/gpio/files/src/gpio.c @@ -0,0 +1,107 @@ +/* + * 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. + */ +//#define DEBUG +//#define VERBOSE + +#include "gpio.h" + +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/errno.h> + +#include <openbmc/log.h> + +void gpio_init_default(gpio_st *g) { + g->gs_gpio = -1; + g->gs_fd = -1; +} + +int gpio_open(gpio_st *g, int gpio) +{ + char buf[128]; + int rc; + + snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%u/value", gpio); + rc = open(buf, O_RDWR); + if (rc == -1) { + rc = errno; + LOG_ERR(rc, "Failed to open %s", buf); + return -rc; + } + g->gs_fd = rc; + g->gs_gpio = gpio; + return 0; +} + +void gpio_close(gpio_st *g) +{ + if (g && g->gs_fd != -1) { + close(g->gs_fd); + } + gpio_init_default(g); +} + +gpio_value_en gpio_read(gpio_st *g) +{ + char buf[32] = {0}; + gpio_value_en v; + lseek(g->gs_fd, 0, SEEK_SET); + read(g->gs_fd, buf, sizeof(buf)); + v = atoi(buf) ? GPIO_VALUE_HIGH : GPIO_VALUE_LOW; + LOG_VER("read gpio=%d value=%d %d", g->gs_gpio, atoi(buf), v); + return v; +} + +void gpio_write(gpio_st *g, gpio_value_en v) +{ + lseek(g->gs_fd, 0, SEEK_SET); + write(g->gs_fd, (v == GPIO_VALUE_HIGH) ? "1" : "0", 1); + LOG_VER("write gpio=%d value=%d", g->gs_gpio, v); +} + +int gpio_change_direction(gpio_st *g, gpio_direction_en dir) +{ + char buf[128]; + char *val; + int fd = -1; + int rc = 0; + + snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%u/direction", g->gs_gpio); + fd = open(buf, O_WRONLY); + if (fd == -1) { + rc = errno; + LOG_ERR(rc, "Failed to open %s", buf); + return -rc; + } + + val = (dir == GPIO_DIRECTION_IN) ? "in" : "out"; + write(fd, val, strlen(val)); + + LOG_VER("change gpio=%d direction=%s", g->gs_gpio, val); + + out: + if (fd != -1) { + close(fd); + } + return -rc; +} diff --git a/common/recipes-lib/gpio/files/src/gpio.h b/common/recipes-lib/gpio/files/src/gpio.h new file mode 100644 index 0000000..3303986 --- /dev/null +++ b/common/recipes-lib/gpio/files/src/gpio.h @@ -0,0 +1,42 @@ +/* + * 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 GPIO_H +#define GPIO_H + +typedef struct { + int gs_gpio; + int gs_fd; +} gpio_st; + +typedef enum { + GPIO_DIRECTION_IN, + GPIO_DIRECTION_OUT, +} gpio_direction_en; + +typedef enum { + GPIO_VALUE_LOW = 0, + GPIO_VALUE_HIGH = 1, +} gpio_value_en; + +int gpio_open(gpio_st* g, int gpio); +void gpio_close(gpio_st *g); +gpio_value_en gpio_read(gpio_st *g); +void gpio_write(gpio_st *g, gpio_value_en v); +int gpio_change_direction(gpio_st *g, gpio_direction_en dir); + +#endif diff --git a/common/recipes-lib/gpio/libgpio_0.1.bb b/common/recipes-lib/gpio/libgpio_0.1.bb new file mode 100644 index 0000000..cd32ac0 --- /dev/null +++ b/common/recipes-lib/gpio/libgpio_0.1.bb @@ -0,0 +1,40 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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 in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +SUMMARY = "GPIO access library" +DESCRIPTION = "library to access GPIO" +SECTION = "base" +PR = "r1" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://gpio.c;beginline=4;endline=16;md5=da35978751a9d71b73679307c4d296ec" + +SRC_URI = "file://src \ + " + +DEPENDS += "liblog" + +S = "${WORKDIR}/src" + +do_install() { + install -d ${D}${libdir} + install -m 0644 libgpio.so ${D}${libdir}/libgpio.so + + install -d ${D}${includedir}/openbmc + install -m 0644 gpio.h ${D}${includedir}/openbmc/gpio.h +} + +FILES_${PN} = "${libdir}/libgpio.so" +FILES_${PN}-dev = "${includedir}/openbmc/gpio.h" diff --git a/common/recipes-lib/ipmb/files/Makefile b/common/recipes-lib/ipmb/files/Makefile new file mode 100644 index 0000000..c09b325 --- /dev/null +++ b/common/recipes-lib/ipmb/files/Makefile @@ -0,0 +1,11 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +lib: libipmb.so + +libipmb.so: ipmb.c + $(CC) $(CFLAGS) -fPIC -c -o ipmb.o ipmb.c + $(CC) -shared -o libipmb.so ipmb.o -lc + +.PHONY: clean + +clean: + rm -rf *.o libipmb.so diff --git a/common/recipes-lib/ipmb/files/ipmb.c b/common/recipes-lib/ipmb/files/ipmb.c new file mode 100644 index 0000000..731eeba --- /dev/null +++ b/common/recipes-lib/ipmb/files/ipmb.c @@ -0,0 +1,82 @@ +/* + * + * 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 <errno.h> +#include <string.h> +#include <syslog.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/un.h> +#include "ipmb.h" + +/* + * Function to handle IPMB messages + */ +void +lib_ipmb_handle(unsigned char bus_id, + unsigned char *request, unsigned char req_len, + unsigned char *response, unsigned char *res_len) { + + int s, t, len; + struct sockaddr_un remote; + char sock_path[64] = {0}; + + sprintf(sock_path, "%s_%d", SOCK_PATH_IPMB, bus_id); + + // TODO: Need to update to reuse the socket instead of creating new + if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { + syslog(LOG_ALERT, "lib_ipmb_handle: socket() failed\n"); + return; + } + + remote.sun_family = AF_UNIX; + strcpy(remote.sun_path, sock_path); + len = strlen(remote.sun_path) + sizeof(remote.sun_family); + + if (connect(s, (struct sockaddr *)&remote, len) == -1) { + syslog(LOG_ALERT, "ipmb_handle: connect() failed\n"); + goto clean_exit; + } + + if (send(s, request, req_len, 0) == -1) { + syslog(LOG_ALERT, "ipmb_handle: send() failed\n"); + goto clean_exit; + } + + if ((t=recv(s, response, MAX_IPMB_RES_LEN, 0)) > 0) { + *res_len = t; + } else { + if (t < 0) { + syslog(LOG_ALERT, "lib_ipmb_handle: recv() failed\n"); + } else { + printf("Server closed connection\n"); + } + } + +clean_exit: + close(s); + + return; +} diff --git a/common/recipes-lib/ipmb/files/ipmb.h b/common/recipes-lib/ipmb/files/ipmb.h new file mode 100644 index 0000000..d9bc16b --- /dev/null +++ b/common/recipes-lib/ipmb/files/ipmb.h @@ -0,0 +1,75 @@ +/* + * + * 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 __IPMB_H__ +#define __IPMB_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#define SOCK_PATH_IPMB "/tmp/ipmb_socket" + +#define BMC_SLAVE_ADDR 0x10 +#define BRIDGE_SLAVE_ADDR 0x20 +#define ZERO_CKSUM_CONST 0x100 + +// rqSA, rsSA, rqSeq, hdrCksum, dataCksum +#define IPMB_HDR_SIZE 5 + +// rqSA, NetFn, hdrCksum +#define IPMB_DATA_OFFSET 3 + +// Slot#0 is on I2C Bus1 +#define IPMB_BUS_SLOT0 1 + +#define TIMEOUT_IPMI 4 +#define MAX_IPMB_RES_LEN 255 + +typedef struct _ipmb_req_t { + uint8_t res_slave_addr; + uint8_t netfn_lun; + uint8_t hdr_cksum; + uint8_t req_slave_addr; + uint8_t seq_lun; + uint8_t cmd; + uint8_t data[]; +} ipmb_req_t; + +typedef struct _ipmb_res_t { + uint8_t req_slave_addr; + uint8_t netfn_lun; + uint8_t hdr_cksum; + uint8_t res_slave_addr; + uint8_t seq_lun; + uint8_t cmd; + uint8_t cc; + uint8_t data[]; +} ipmb_res_t; + +void lib_ipmb_handle(unsigned char bus_id, + unsigned char *request, unsigned char req_len, + unsigned char *response, unsigned char *res_len); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* __IPMB_H__ */ diff --git a/common/recipes-lib/ipmb/libipmb_0.1.bb b/common/recipes-lib/ipmb/libipmb_0.1.bb new file mode 100644 index 0000000..81eed9c --- /dev/null +++ b/common/recipes-lib/ipmb/libipmb_0.1.bb @@ -0,0 +1,26 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +SUMMARY = "IPMB Client Library" +DESCRIPTION = "library for IPMB Client" +SECTION = "base" +PR = "r1" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://ipmb.c;beginline=8;endline=20;md5=da35978751a9d71b73679307c4d296ec" + + +SRC_URI = "file://Makefile \ + file://ipmb.c \ + file://ipmb.h \ + " + +S = "${WORKDIR}" + +do_install() { + install -d ${D}${libdir} + install -m 0644 libipmb.so ${D}${libdir}/libipmb.so + + install -d ${D}${includedir}/openbmc + install -m 0644 ipmb.h ${D}${includedir}/openbmc/ipmb.h +} + +FILES_${PN} = "${libdir}/libipmb.so" +FILES_${PN}-dev = "${includedir}/openbmc/ipmb.h" diff --git a/common/recipes-lib/ipmi/files/Makefile b/common/recipes-lib/ipmi/files/Makefile new file mode 100644 index 0000000..369819c --- /dev/null +++ b/common/recipes-lib/ipmi/files/Makefile @@ -0,0 +1,27 @@ +# Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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 in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA + +lib: libipmi.so + +libipmi.so: ipmi.c + $(CC) $(CFLAGS) -fPIC -c -o ipmi.o ipmi.c + $(CC) -shared -o libipmi.so ipmi.o -lc + +.PHONY: clean + +clean: + rm -rf *.o libipmi.so diff --git a/common/recipes-lib/ipmi/files/ipmi.c b/common/recipes-lib/ipmi/files/ipmi.c new file mode 100644 index 0000000..3579eca --- /dev/null +++ b/common/recipes-lib/ipmi/files/ipmi.c @@ -0,0 +1,80 @@ +/* + * + * Copyright 2014-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 "ipmi.h" +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <string.h> +#include <syslog.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/un.h> + +#define MAX_IPMI_RES_LEN 100 + +/* + * Function to handle IPMI messages + */ +void +lib_ipmi_handle(unsigned char *request, unsigned char req_len, + unsigned char *response, unsigned char *res_len) { + + int s, t, len; + struct sockaddr_un remote; + + // TODO: Need to update to reuse the socket instead of creating new + if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { + syslog(LOG_ALERT, "lib_ipmi_handle: socket() failed\n"); + return; + } + + remote.sun_family = AF_UNIX; + strcpy(remote.sun_path, SOCK_PATH_IPMI); + len = strlen(remote.sun_path) + sizeof(remote.sun_family); + + if (connect(s, (struct sockaddr *)&remote, len) == -1) { + syslog(LOG_ALERT, "lib_ipmi_handle: connect() failed\n"); + return; + } + + if (send(s, request, req_len, 0) == -1) { + syslog(LOG_ALERT, "lib_ipmi_handle: send() failed\n"); + return; + } + + if ((t=recv(s, response, MAX_IPMI_RES_LEN, 0)) > 0) { + *res_len = t; + } else { + if (t < 0) { + syslog(LOG_ALERT, "lib_ipmi_handle: recv() failed\n"); + } else { + printf("Server closed connection"); + } + + return; + } + + close(s); + + return; +} diff --git a/common/recipes-lib/ipmi/files/ipmi.h b/common/recipes-lib/ipmi/files/ipmi.h new file mode 100644 index 0000000..2ae7f1c --- /dev/null +++ b/common/recipes-lib/ipmi/files/ipmi.h @@ -0,0 +1,453 @@ +/* + * + * 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 __IPMI_H__ +#define __IPMI_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdint.h> + +#define SOCK_PATH_IPMI "/tmp/ipmi_socket" + +#define IPMI_SEL_VERSION 0x51 +#define IPMI_SDR_VERSION 0x51 + +#define MAX_NUM_DIMMS 4 + +#define SIZE_AUTH_ENABLES 5 +#define SIZE_IP_ADDR 4 +#define SIZE_MAC_ADDR 6 +#define SIZE_NET_MASK 4 +#define SIZE_IP_HDR 3 +#define SIZE_RMCP_PORT 2 +#define SIZE_COMMUNITY_STR 18 +#define SIZE_DEST_TYPE 4 +#define SIZE_DEST_ADDR 18 +#define SIZE_TIME_STAMP 4 + +#define SIZE_PROC_FREQ 2 +#define SIZE_DIMM_SPEED 2 +#define SIZE_DIMM_SIZE 2 + +#define SIZE_SYSFW_VER 17 +#define SIZE_SYS_NAME 17 +#define SIZE_OS_NAME 17 +#define SIZE_OS_VER 17 +#define SIZE_BMC_URL 17 +#define SIZE_OS_HV_URL 17 + +#define SIZE_SEL_REC 16 + +#define BIC_INTF_HDR_SIZE 3 + +#define LUN_OFFSET 2 + +//NetFn, Cmd +#define IPMI_REQ_HDR_SIZE 2 + +// NetFn, Cmd, CC +#define IPMI_RESP_HDR_SIZE 3 + +#define MAX_IPMI_MSG_SIZE 100 + +// Type Definition +#define TYPE_BINARY 0 +#define TYPE_BCD_PLUS 1 +#define TYPE_ASCII_6BIT 2 +#define TYPE_ASCII_8BIT 3 + +// IPMI request Structure (IPMI/Section 9.2) +typedef struct +{ + unsigned char netfn_lun; + unsigned char cmd; + unsigned char data[]; +} ipmi_req_t; + +// IPMI Multi Node request Structure +// Supports additional member to identify the node# +typedef struct +{ + unsigned char payload_id; + unsigned char netfn_lun; + unsigned char cmd; + unsigned char data[]; +} ipmi_mn_req_t; + +// IPMI response Structure (IPMI/Section 9.3) +typedef struct +{ + unsigned char netfn_lun; + unsigned char cmd; + unsigned char cc; + unsigned char data[]; +} ipmi_res_t; + +// IPMI/Spec Table 20-2 +typedef struct _ipmi_dev_id_t { + uint8_t dev_id; + uint8_t dev_rev; + uint8_t fw_rev1; + uint8_t fw_rev2; + uint8_t ipmi_ver; + uint8_t dev_support; + uint8_t mfg_id[3]; + uint8_t prod_id[2]; + uint8_t aux_fw_rev[4]; +} ipmi_dev_id_t; + + +typedef struct _ipmi_fruid_info_t { + uint8_t size_lsb; + uint8_t size_msb; + uint8_t bytes_words; +} ipmi_fruid_info_t; + +#pragma pack(push, 1) + +// 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; + +typedef struct _ipmi_sel_sdr_info_t { + uint8_t ver; + uint16_t rec_count; + uint16_t free_space; + uint8_t add_ts[4]; + uint8_t erase_ts[4]; + uint8_t oper; +} ipmi_sel_sdr_info_t; + +typedef struct _ipmi_sel_sdr_req_t { + uint16_t rsv_id; + uint16_t rec_id; + uint8_t offset; + uint8_t nbytes; +} ipmi_sel_sdr_req_t; + +typedef struct _ipmi_sel_sdr_res_t { + uint16_t next_rec_id; + uint8_t data[]; +} ipmi_sel_sdr_res_t; + +#pragma pack(pop) + +// LAN Configuration Structure (IPMI/Table 23.4) +typedef struct +{ + unsigned char set_in_prog; + unsigned char auth_support; + unsigned char auth_enables[SIZE_AUTH_ENABLES]; + unsigned char ip_addr[SIZE_IP_ADDR]; + unsigned char ip_src; + unsigned char mac_addr[SIZE_MAC_ADDR]; + unsigned char net_mask[SIZE_NET_MASK]; + unsigned char ip_hdr[SIZE_IP_HDR]; + unsigned char pri_rmcp_port[SIZE_RMCP_PORT]; + unsigned char sec_rmcp_port[SIZE_RMCP_PORT]; + unsigned char arp_ctrl; + unsigned char garp_interval; + unsigned char df_gw_ip_addr[SIZE_IP_ADDR]; + unsigned char df_gw_mac_addr[SIZE_MAC_ADDR]; + unsigned char back_gw_ip_addr[SIZE_IP_ADDR]; + unsigned char back_gw_mac_addr[SIZE_MAC_ADDR]; + unsigned char community_str[SIZE_COMMUNITY_STR]; + unsigned char no_of_dest; + unsigned char dest_type[SIZE_DEST_TYPE]; + unsigned char dest_addr[SIZE_DEST_ADDR]; +} lan_config_t; + +// Structure to store Processor Information +typedef struct +{ + unsigned char type; + unsigned char freq[SIZE_PROC_FREQ]; +} proc_info_t; + +// Structure to store DIMM Information +typedef struct +{ + unsigned char type; + unsigned char speed[SIZE_DIMM_SPEED]; + unsigned char size[SIZE_DIMM_SIZE]; +} dimm_info_t; + + +// Structure for System Info Params (IPMI/Section 22.14a) +typedef struct +{ + unsigned char set_in_prog; + unsigned char sysfw_ver[SIZE_SYSFW_VER]; + unsigned char sys_name[SIZE_SYS_NAME]; + unsigned char pri_os_name[SIZE_OS_NAME]; + unsigned char present_os_name[SIZE_OS_NAME]; + unsigned char present_os_ver[SIZE_OS_VER]; + unsigned char bmc_url[SIZE_BMC_URL]; + unsigned char os_hv_url[SIZE_OS_HV_URL]; +} sys_info_param_t; + +// Structure for Sensor Reading (IPMI/Section 35.14) +typedef struct +{ + uint8_t value; + uint8_t flags; + uint8_t status; + uint8_t ext_status; +} ipmi_sensor_reading_t; + +// Network Function Codes (IPMI/Section 5.1) +enum +{ + NETFN_CHASSIS_REQ = 0x00, + NETFN_CHASSIS_RES, + NETFN_BRIDGE_REQ, + NETFN_BRIDGE_RES, + NETFN_SENSOR_REQ, + NETFN_SENSOR_RES, + NETFN_APP_REQ, + NETFN_APP_RES, + NETFN_FIRMWARE_REQ, + NETFN_FIRMWARE_RES, + NETFN_STORAGE_REQ, + NETFN_STORAGE_RES, + NETFN_TRANSPORT_REQ, + NETFN_TRANSPORT_RES, + NETFN_OEM_REQ = 0x30, + NETFN_OEM_RES = 0x31, + NETFN_OEM_1S_REQ = 0x38, + NETFN_OEM_1S_RES = 0x39, +}; + +// Chassis Command Codes (IPMI/Table H-1) +enum +{ + CMD_CHASSIS_GET_STATUS = 0x01, + CMD_CHASSIS_GET_BOOT_OPTIONS = 0x09, +}; + + +// Application Command Codes (IPMI/Table H-1) +enum +{ + CMD_APP_GET_DEVICE_ID = 0x01, + CMD_APP_GET_SELFTEST_RESULTS = 0x04, + CMD_APP_GET_DEVICE_GUID = 0x08, + CMD_APP_RESET_WDT = 0x22, + CMD_APP_SET_WDT = 0x24, + CMD_APP_GET_WDT = 0x25, + CMD_APP_GET_GLOBAL_ENABLES = 0x2F, + CMD_APP_GET_SYSTEM_GUID = 0x37, + CMD_APP_SET_SYS_INFO_PARAMS = 0x58, + CMD_APP_GET_SYS_INFO_PARAMS = 0x59, +}; + +// Storage Command Codes (IPMI/Table H-1) +enum +{ + CMD_STORAGE_GET_FRUID_INFO = 0x10, + CMD_STORAGE_READ_FRUID_DATA = 0x11, + CMD_STORAGE_GET_SDR_INFO = 0x20, + CMD_STORAGE_RSV_SDR = 0x22, + CMD_STORAGE_GET_SDR = 0x23, + CMD_STORAGE_GET_SEL_INFO = 0x40, + CMD_STORAGE_RSV_SEL = 0x42, + CMD_STORAGE_GET_SEL = 0x43, + CMD_STORAGE_ADD_SEL = 0x44, + CMD_STORAGE_CLR_SEL = 0x47, + CMD_STORAGE_GET_SEL_TIME = 0x48, + CMD_STORAGE_GET_SEL_UTC = 0x5C, +}; + +// Sensor Command Codes (IPMI/Table H-1) +enum +{ + CMD_SENSOR_GET_SENSOR_READING = 0x2D, +}; + +// Transport Command Codes (IPMI/Table H-1) +enum +{ + CMD_TRANSPORT_SET_LAN_CONFIG = 0x01, + CMD_TRANSPORT_GET_LAN_CONFIG = 0x02, +}; + +// OEM Command Codes (Quanta/FB defined commands) +enum +{ + CMD_OEM_SET_PROC_INFO = 0x1A, + CMD_OEM_SET_DIMM_INFO = 0x1C, + CMD_OEM_SET_POST_START = 0x73, + CMD_OEM_SET_POST_END = 0x74, +}; + +// OEM 1S Command Codes (Quanta/FB defined commands) +enum +{ + CMD_OEM_1S_MSG_IN = 0x1, + CMD_OEM_1S_GET_GPIO = 0x3, + CMD_OEM_1S_GET_GPIO_CONFIG = 0x5, + CMD_OEM_1S_SET_GPIO_CONFIG = 0x6, + CMD_OEM_1S_INTR = 0x7, + CMD_OEM_1S_POST_BUF = 0x8, + CMD_OEM_1S_GET_CONFIG = 0xE, + CMD_OEM_1S_PLAT_DISC = 0xF, + CMD_OEM_1S_SET_CONFIG = 0x10, + CMD_OEM_1S_BIC_RESET = 0x11, + CMD_OEM_1S_GET_POST_BUF = 0x12, + CMD_OEM_1S_BIC_UPDATE_MODE = 0x13, +}; + + +// IPMI command Completion Codes (IPMI/Section 5.2) +enum +{ + CC_SUCCESS = 0x00, + CC_INVALID_PARAM = 0x80, + CC_SEL_ERASE_PROG = 0x81, + CC_INVALID_CMD = 0xC1, + CC_PARAM_OUT_OF_RANGE = 0xC9, + CC_UNSPECIFIED_ERROR = 0xFF, +}; + +// LAN Configuration parameters (IPMI/Table 23-4) +enum +{ + LAN_PARAM_SET_IN_PROG, + LAN_PARAM_AUTH_SUPPORT, + LAN_PARAM_AUTH_ENABLES, + LAN_PARAM_IP_ADDR, + LAN_PARAM_IP_SRC, + LAN_PARAM_MAC_ADDR, + LAN_PARAM_NET_MASK, + LAN_PARAM_IP_HDR, + LAN_PARAM_PRI_RMCP_PORT, + LAN_PARAM_SEC_RMCP_PORT, + LAN_PARAM_ARP_CTRL, + LAN_PARAM_GARP_INTERVAL, + LAN_PARAM_DF_GW_IP_ADDR, + LAN_PARAM_DF_GW_MAC_ADDR, + LAN_PARAM_BACK_GW_IP_ADDR, + LAN_PARAM_BACK_GW_MAC_ADDR, + LAN_PARAM_COMMUNITY_STR, + LAN_PARAM_NO_OF_DEST, + LAN_PARAM_DEST_TYPE, + LAN_PARAM_DEST_ADDR, +}; + +// Boot Option Parameters (IPMI/Table 28-14) +enum +{ + PARAM_SET_IN_PROG = 0x00, + PARAM_SVC_PART_SELECT, + PARAM_SVC_PART_SCAN, + PARAM_BOOT_FLAG_CLR, + PARAM_BOOT_INFO_ACK, + PARAM_BOOT_FLAGS, + PARAM_BOOT_INIT_INFO, +}; + +//System Info Parameters (IPMI/Table 22-16c) +enum +{ + SYS_INFO_PARAM_SET_IN_PROG, + SYS_INFO_PARAM_SYSFW_VER, + SYS_INFO_PARAM_SYS_NAME, + SYS_INFO_PARAM_PRI_OS_NAME, + SYS_INFO_PARAM_PRESENT_OS_NAME, + SYS_INFO_PARAM_PRESENT_OS_VER, + SYS_INFO_PARAM_BMC_URL, + SYS_INFO_PARAM_OS_HV_URL, +}; + +// Bridge-IC interface on which this command initiated +enum +{ + BIC_INTF_ME = 0x01, + BIC_INTF_SOL = 0x02, + BIC_INTF_KCS = 0x03, +}; + +void lib_ipmi_handle(unsigned char *request, unsigned char req_len, + unsigned char *response, unsigned char *res_len); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* __IPMI_H__ */ diff --git a/common/recipes-lib/ipmi/libipmi_0.2.bb b/common/recipes-lib/ipmi/libipmi_0.2.bb new file mode 100644 index 0000000..c5bca76 --- /dev/null +++ b/common/recipes-lib/ipmi/libipmi_0.2.bb @@ -0,0 +1,41 @@ +# Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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 in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +SUMMARY = "IPMI Client Library" +DESCRIPTION = "library for IPMI Client" +SECTION = "base" +PR = "r1" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://ipmi.c;beginline=8;endline=20;md5=da35978751a9d71b73679307c4d296ec" + + +SRC_URI = "file://Makefile \ + file://ipmi.c \ + file://ipmi.h \ + " + +S = "${WORKDIR}" + +do_install() { + install -d ${D}${libdir} + install -m 0644 libipmi.so ${D}${libdir}/libipmi.so + + install -d ${D}${includedir}/openbmc + install -m 0644 ipmi.h ${D}${includedir}/openbmc/ipmi.h +} + +FILES_${PN} = "${libdir}/libipmi.so" +FILES_${PN}-dev = "${includedir}/openbmc/ipmi.h" diff --git a/common/recipes-lib/log/files/src/log.h b/common/recipes-lib/log/files/src/log.h new file mode 100644 index 0000000..a69d69e --- /dev/null +++ b/common/recipes-lib/log/files/src/log.h @@ -0,0 +1,59 @@ +/* + * 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 LOG_H +#define LOG_H + +#include <stdio.h> +#include <string.h> + +//#define DEBUG +//#define VERBOSE + +#define _LOG(dst, fmt, ...) do { \ + fprintf(dst, "%s:%d " fmt "\n", \ + __FUNCTION__, __LINE__, ##__VA_ARGS__); \ + fflush(dst); \ +} while(0) + +#define LOG_ERR(err, fmt, ...) do { \ + char buf[128]; \ + strerror_r(err, buf, sizeof(buf)); \ + _LOG(stderr, "ERROR " fmt ": %s", ##__VA_ARGS__, buf); \ +} while(0) + +#define LOG_INFO(fmt, ...) do { \ + _LOG(stdout, fmt, ##__VA_ARGS__); \ +} while(0) + +#ifdef DEBUG +#define LOG_DBG(fmt, ...) do { \ + _LOG(stdout, fmt, ##__VA_ARGS__); \ +} while(0) +#else +#define LOG_DBG(fmt, ...) +#endif + +#ifdef VERBOSE +#define LOG_VER(fmt, ...) do { \ + _LOG(stdout, fmt, ##__VA_ARGS__); \ +} while(0) +#else +#define LOG_VER(fmt, ...) +#endif + +#endif diff --git a/common/recipes-lib/log/liblog_0.1.bb b/common/recipes-lib/log/liblog_0.1.bb new file mode 100644 index 0000000..8034c0d --- /dev/null +++ b/common/recipes-lib/log/liblog_0.1.bb @@ -0,0 +1,36 @@ +# Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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 in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA + +SUMMARY = "Log util functions" +DESCRIPTION = "some macros to log" +SECTION = "dev" +PR = "r1" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://log.h;beginline=4;endline=16;md5=da35978751a9d71b73679307c4d296ec" + +SRC_URI += "file://src \ + " + +S = "${WORKDIR}/src" + +do_install() { + # common lib and include files + install -d ${D}${includedir}/openbmc + install -m 0644 log.h ${D}${includedir}/openbmc/log.h +} + +FILES_${PN}-dev = "${includedir}/openbmc/log.h" 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" |