diff options
Diffstat (limited to 'meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp')
6 files changed, 470 insertions, 0 deletions
diff --git a/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/.clang-format b/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/.clang-format new file mode 100644 index 000000000..86a2a9d63 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/.clang-format @@ -0,0 +1,21 @@ +--- +BasedOnStyle: LLVM +Language: Cpp +IndentWidth: 8 +UseTab: Always +BreakBeforeBraces: Linux +AlwaysBreakBeforeMultilineStrings: true +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +AllowShortFunctionsOnASingleLine: false +IndentCaseLabels: false +AlignEscapedNewlinesLeft: false +AlignTrailingComments: true +AllowAllParametersOfDeclarationOnNextLine: false +AlignAfterOpenBracket: true +SpaceAfterCStyleCast: false +MaxEmptyLinesToKeep: 2 +BreakBeforeBinaryOperators: NonAssignment +BreakStringLiterals: false +SortIncludes: true +ContinuationIndentWidth: 8 diff --git a/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/0001-Add-smbus-support-to-Cmake-Lists.patch b/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/0001-Add-smbus-support-to-Cmake-Lists.patch new file mode 100644 index 000000000..8bb9ce485 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/0001-Add-smbus-support-to-Cmake-Lists.patch @@ -0,0 +1,36 @@ +From 21f2f29129a7eba8aecdf07875004bafc6a74269 Mon Sep 17 00:00:00 2001 +From: James Feist <james.feist@linux.intel.com> +Date: Thu, 20 Jun 2019 08:58:44 -0700 +Subject: [PATCH] Add smbus support to Cmake Lists + +This adds smbus changes needed for libmctp. + +Change-Id: I06fc950337e6f3d5b1cef0fb445be2d448d49e44 +Signed-off-by: James Feist <james.feist@linux.intel.com> +--- + CMakeLists.txt | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index a5b1042..04c4bdf 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -3,7 +3,7 @@ cmake_minimum_required (VERSION 3.5 FATAL_ERROR) + add_definitions (-DMCTP_LOG_STDERR) + add_definitions (-DMCTP_FILEIO) + +-add_library (libmctp STATIC alloc.c core.c log.c libmctp.h serial.c) ++add_library (libmctp STATIC alloc.c core.c log.c libmctp.h serial.c smbus.c) + + target_include_directories (libmctp PUBLIC + $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}> +@@ -18,5 +18,5 @@ add_executable (test_seq tests/test_seq.c tests/test-utils.c) + target_link_libraries (test_seq libmctp) + + install (TARGETS libmctp DESTINATION lib) +-install (FILES libmctp.h DESTINATION include) ++install (FILES libmctp.h libmctp-smbus.h libmctp-serial.h DESTINATION include) + +-- +2.17.1 + diff --git a/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/crc32c.c b/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/crc32c.c new file mode 100644 index 000000000..0d5090e2c --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/crc32c.c @@ -0,0 +1,93 @@ +#include "crc32c.h" +/*****************************************************************/ +/* */ +/* CRC LOOKUP TABLE */ +/* ================ */ +/* The following CRC lookup table was generated automagically */ +/* by the Rocksoft^tm Model CRC Algorithm Table Generation */ +/* Program V1.0 using the following model parameters: */ +/* */ +/* Width : 4 bytes. */ +/* Poly : 0x1EDC6F41L */ +/* Reverse : TRUE. */ +/* */ +/* For more information on the Rocksoft^tm Model CRC Algorithm, */ +/* see the document titled "A Painless Guide to CRC Error */ +/* Detection Algorithms" by Ross Williams */ +/* (ross@guest.adelaide.edu.au.). This document is likely to be */ +/* in the FTP archive "ftp.adelaide.edu.au/pub/rocksoft". */ +/* */ +/*****************************************************************/ + +unsigned long crctable[256] = { + 0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L, 0xC79A971FL, + 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL, 0x8AD958CFL, 0x78B2DBCCL, + 0x6BE22838L, 0x9989AB3BL, 0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, + 0x5E133C24L, 0x105EC76FL, 0xE235446CL, 0xF165B798L, 0x030E349BL, + 0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L, 0x9A879FA0L, + 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L, 0x5D1D08BFL, 0xAF768BBCL, + 0xBC267848L, 0x4E4DFB4BL, 0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, + 0x33ED7D2AL, 0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L, + 0xAA64D611L, 0x580F5512L, 0x4B5FA6E6L, 0xB93425E5L, 0x6DFE410EL, + 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL, 0x30E349B1L, 0xC288CAB2L, + 0xD1D83946L, 0x23B3BA45L, 0xF779DEAEL, 0x05125DADL, 0x1642AE59L, + 0xE4292D5AL, 0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL, + 0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L, 0x417B1DBCL, + 0xB3109EBFL, 0xA0406D4BL, 0x522BEE48L, 0x86E18AA3L, 0x748A09A0L, + 0x67DAFA54L, 0x95B17957L, 0xCBA24573L, 0x39C9C670L, 0x2A993584L, + 0xD8F2B687L, 0x0C38D26CL, 0xFE53516FL, 0xED03A29BL, 0x1F682198L, + 0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L, 0x96BF4DCCL, + 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L, 0xDBFC821CL, 0x2997011FL, + 0x3AC7F2EBL, 0xC8AC71E8L, 0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, + 0x0F36E6F7L, 0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L, + 0xA65C047DL, 0x5437877EL, 0x4767748AL, 0xB50CF789L, 0xEB1FCBADL, + 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L, 0x2C855CB2L, 0xDEEEDFB1L, + 0xCDBE2C45L, 0x3FD5AF46L, 0x7198540DL, 0x83F3D70EL, 0x90A324FAL, + 0x62C8A7F9L, 0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L, + 0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L, 0x3CDB9BDDL, + 0xCEB018DEL, 0xDDE0EB2AL, 0x2F8B6829L, 0x82F63B78L, 0x709DB87BL, + 0x63CD4B8FL, 0x91A6C88CL, 0x456CAC67L, 0xB7072F64L, 0xA457DC90L, + 0x563C5F93L, 0x082F63B7L, 0xFA44E0B4L, 0xE9141340L, 0x1B7F9043L, + 0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL, 0x92A8FC17L, + 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L, 0x55326B08L, 0xA759E80BL, + 0xB4091BFFL, 0x466298FCL, 0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, + 0x0B21572CL, 0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L, + 0xA24BB5A6L, 0x502036A5L, 0x4370C551L, 0xB11B4652L, 0x65D122B9L, + 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL, 0x2892ED69L, 0xDAF96E6AL, + 0xC9A99D9EL, 0x3BC21E9DL, 0xEF087A76L, 0x1D63F975L, 0x0E330A81L, + 0xFC588982L, 0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL, + 0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L, 0x38CC2A06L, + 0xCAA7A905L, 0xD9F75AF1L, 0x2B9CD9F2L, 0xFF56BD19L, 0x0D3D3E1AL, + 0x1E6DCDEEL, 0xEC064EEDL, 0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, + 0xD0DDD530L, 0x0417B1DBL, 0xF67C32D8L, 0xE52CC12CL, 0x1747422FL, + 0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL, 0x8ECEE914L, + 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L, 0xD3D3E1ABL, 0x21B862A8L, + 0x32E8915CL, 0xC083125FL, 0x144976B4L, 0xE622F5B7L, 0xF5720643L, + 0x07198540L, 0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L, + 0x9E902E7BL, 0x6CFBAD78L, 0x7FAB5E8CL, 0x8DC0DD8FL, 0xE330A81AL, + 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL, 0x24AA3F05L, 0xD6C1BC06L, + 0xC5914FF2L, 0x37FACCF1L, 0x69E9F0D5L, 0x9B8273D6L, 0x88D28022L, + 0x7AB90321L, 0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL, + 0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L, 0x34F4F86AL, + 0xC69F7B69L, 0xD5CF889DL, 0x27A40B9EL, 0x79B737BAL, 0x8BDCB4B9L, + 0x988C474DL, 0x6AE7C44EL, 0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, + 0xAD7D5351L}; + +/*****************************************************************/ +/* End of CRC Lookup Table */ +/*****************************************************************/ + +uint32_t crc32c(uint8_t *data, int length) +{ + const uint32_t CRC_INIT = 0xffffffffL; + const uint32_t XO_ROT = 0xffffffffL; + + uint32_t crc = CRC_INIT; + + while (length--) { + crc = crctable[(crc ^ *data++) & 0xFFL] ^ (crc >> 8); + } + crc = crc ^ XO_ROT; + + return crc; +} diff --git a/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/crc32c.h b/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/crc32c.h new file mode 100644 index 000000000..d6b1d11e2 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/crc32c.h @@ -0,0 +1,9 @@ +#ifndef CRC32C_H +#define CRC32C_H + +#include <stdint.h> +#include <stdlib.h> + +uint32_t crc32c(uint8_t *buf, int len); + +#endif /* CRC32C_H */ diff --git a/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/libmctp-smbus.h b/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/libmctp-smbus.h new file mode 100644 index 000000000..b3beadb0c --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/libmctp-smbus.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef _LIBMCTP_SMBUS_H +#define _LIBMCTP_SMBUS_H + +#include "libmctp.h" + +struct mctp_binding_smbus; + +struct mctp_binding_smbus *mctp_smbus_init(void); +int mctp_smbus_get_out_fd(struct mctp_binding_smbus *smbus); +int mctp_smbus_get_in_fd(struct mctp_binding_smbus *smbus); +void mctp_smbus_register_bus(struct mctp_binding_smbus *smbus, + struct mctp *mctp, mctp_eid_t eid); +int mctp_smbus_read(struct mctp_binding_smbus *smbus); +int mctp_smbus_open_bus(struct mctp_binding_smbus *smbus, int out_bus_num, + int root_bus_num); +#endif /* _LIBMCTP_SMBUS_H */ diff --git a/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/smbus.c b/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/smbus.c new file mode 100644 index 000000000..8679a5185 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/smbus.c @@ -0,0 +1,293 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include <assert.h> +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#ifdef MCTP_FILEIO +#include <fcntl.h> +#endif + +#define pr_fmt(x) "smbus: " x + +#include <i2c/smbus.h> +#include <linux/i2c-dev.h> +#include <linux/i2c.h> +#include <sys/ioctl.h> + +#include "libmctp-alloc.h" +#include "libmctp-log.h" +#include "libmctp-smbus.h" +#include "libmctp.h" + +struct mctp_binding_smbus { + struct mctp_binding binding; + struct mctp *mctp; + int out_fd; + int in_fd; + + unsigned long bus_id; + + /* receive buffer */ + uint8_t rxbuf[1024]; + struct mctp_pktbuf *rx_pkt; + + /* temporary transmit buffer */ + uint8_t txbuf[256]; +}; + +#ifndef container_of +#define container_of(ptr, type, member) \ + (type *)((char *)(ptr) - (char *)&((type *)0)->member) +#endif + +#define binding_to_smbus(b) container_of(b, struct mctp_binding_smbus, binding) + +#define MCTP_COMMAND_CODE 0x0F +#define MCTP_SLAVE_ADDRESS 0x1d +#define MCTP_SOURCE_SLAVE_ADDRESS 0x21 + +#define SMBUS_PEC_BYTE_SIZE 1 + +struct mctp_smbus_header_tx { + uint8_t source_slave_address; +}; + +struct mctp_smbus_header_rx { + uint8_t destination_slave_address; + uint8_t command_code; + uint8_t byte_count; + uint8_t source_slave_address; +}; + +static int mctp_binding_smbus_tx(struct mctp_binding *b, + struct mctp_pktbuf *pkt) +{ + struct mctp_binding_smbus *smbus = binding_to_smbus(b); + struct mctp_smbus_header_tx *hdr; + uint8_t *buf; + size_t len; + int r; + struct i2c_msg msg; + struct i2c_rdwr_ioctl_data data; + + data.msgs = &msg; + data.nmsgs = 1; + + uint16_t timeout = 1000; + int i; + + /* the length field in the header excludes smbus framing + * and escape sequences */ + len = mctp_pktbuf_size(pkt); + + hdr = (void *)smbus->txbuf; + + // hdr->len = len + 1; // +1 for PET byte + hdr->source_slave_address = MCTP_SOURCE_SLAVE_ADDRESS; + + buf = (void *)(hdr + sizeof(*hdr)); + + if (len + sizeof(*hdr) > sizeof(smbus->txbuf)) + return -1; + + memcpy(buf, &pkt->data[pkt->start], len); + + buf += len; + + if (ioctl(smbus->out_fd, I2C_SLAVE, MCTP_SLAVE_ADDRESS) < 0) { + mctp_prerr("Can't set slave"); + return -1; + } + if (ioctl(smbus->out_fd, I2C_PEC, 1) < 0) { + mctp_prerr("Cant set PEC byte"); + return -1; + } + + if (i2c_smbus_write_block_data(smbus->out_fd, MCTP_COMMAND_CODE, + sizeof(*hdr) + len, (void *)smbus->txbuf) + < 0) { + mctp_prerr("Failed to send"); + return -1; + } + + return 0; +} + +#ifdef MCTP_FILEIO +int mctp_smbus_read(struct mctp_binding_smbus *smbus) +{ + ssize_t len; + int r; + struct mctp_smbus_header_rx *hdr; + + r = lseek(smbus->in_fd, 0, SEEK_SET); + if (r < 0) { + mctp_prerr("Failed to seek"); + return -1; + } + len = read(smbus->in_fd, smbus->rxbuf, sizeof(smbus->rxbuf)); + if (len < sizeof(*hdr)) { + // TODO Don't return an error here, as it seems to happen from + // time to time, even with a properly written poll loop, + // although it's not clear why. + return 0; + } + + hdr = (void *)smbus->rxbuf; + if (hdr->destination_slave_address + != (MCTP_SOURCE_SLAVE_ADDRESS & ~1)) { + mctp_prerr("Got bad slave address %d", + hdr->destination_slave_address); + return 0; + } + if (hdr->command_code != MCTP_COMMAND_CODE) { + mctp_prerr("Got bad command code %d", hdr->command_code); + // Not a payload intended for us + return 0; + } + + if (hdr->byte_count != (len - sizeof(*hdr))) { + // Got an incorrectly sized payload + mctp_prerr("Got smbus payload sized %d, expecting %d", + hdr->byte_count, len - sizeof(*hdr)); + return 0; + } + + if (len < 0) { + mctp_prerr("can't read from smbus device: %m"); + return -1; + } + + smbus->rx_pkt = mctp_pktbuf_alloc(0); + assert(smbus->rx_pkt); + + if (mctp_pktbuf_push(smbus->rx_pkt, &smbus->rxbuf[sizeof(*hdr)], + len - sizeof(*hdr) - SMBUS_PEC_BYTE_SIZE) + != 0) { + mctp_prerr("Can't push tok pktbuf: %m"); + return -1; + } + + mctp_bus_rx(&(smbus->binding), smbus->rx_pkt); + + mctp_pktbuf_free(smbus->rx_pkt); + smbus->rx_pkt = NULL; + + return 0; +} + +int mctp_smbus_get_in_fd(struct mctp_binding_smbus *smbus) +{ + return smbus->in_fd; +} + +int mctp_smbus_get_out_fd(struct mctp_binding_smbus *smbus) +{ + return smbus->out_fd; +} + +int mctp_smbus_open_bus(struct mctp_binding_smbus *smbus, int out_bus_num, + int root_bus_num) +{ + char filename[60]; + size_t filename_size; + char slave_mqueue[20]; + size_t mqueue_size; + + int fd; + + size_t size; + int address_7_bit; + + address_7_bit = MCTP_SOURCE_SLAVE_ADDRESS >> 1; + size = sizeof(filename); + snprintf(filename, size, + "/sys/bus/i2c/devices/i2c-%d/%d-%04x/slave-mqueue", + root_bus_num, root_bus_num, + (address_7_bit << 8) + address_7_bit); + + smbus->in_fd = open(filename, O_RDONLY | O_NONBLOCK | O_CLOEXEC); + if (smbus->in_fd < 0) { + // Device doesn't exist. Create it. + filename_size = sizeof(filename); + snprintf(filename, filename_size, + "/sys/bus/i2c/devices/i2c-%d/new_device", + root_bus_num); + filename[filename_size - 1] = '\0'; + + fd = open(filename, O_WRONLY); + if (fd < 0) { + mctp_prerr("can't open root device %s: %m", filename); + return -1; + } + + mqueue_size = sizeof(slave_mqueue); + snprintf(slave_mqueue, mqueue_size, "slave-mqueue %#04x", + (address_7_bit << 8) + address_7_bit); + + size = write(fd, slave_mqueue, mqueue_size); + close(fd); + if (size != mqueue_size) { + mctp_prerr("can't create mqueue device on %s: %m", + filename); + return -1; + } + + size = sizeof(filename); + snprintf(filename, size, + "/sys/bus/i2c/devices/i2c-%d/%d-%04x/slave-mqueue", + root_bus_num, root_bus_num, + (address_7_bit << 8) + address_7_bit); + + smbus->in_fd = + open(filename, O_RDONLY | O_NONBLOCK | O_CLOEXEC); + if (smbus->in_fd < 0) { + mctp_prerr("can't open mqueue device on %s: %m", + filename); + return -2; + } + } + + size = sizeof(filename); + snprintf(filename, size, "/dev/i2c-%d", out_bus_num); + filename[size - 1] = '\0'; + + smbus->out_fd = open(filename, O_RDWR | O_NONBLOCK); + if (smbus->out_fd < 0) { + close(smbus->in_fd); + mctp_prerr("can't open device %s: %m", filename); + } + + return 0; +} + +#endif + +void mctp_smbus_register_bus(struct mctp_binding_smbus *smbus, + struct mctp *mctp, mctp_eid_t eid) +{ + assert(smbus->out_fd >= 0); + assert(smbus->in_fd >= 0); + smbus->mctp = mctp; + smbus->bus_id = mctp_register_bus(mctp, &smbus->binding, eid); +} + +struct mctp_binding_smbus *mctp_smbus_init(void) +{ + struct mctp_binding_smbus *smbus; + + smbus = __mctp_alloc(sizeof(*smbus)); + smbus->in_fd = -1; + smbus->out_fd = -1; + + smbus->rx_pkt = NULL; + smbus->binding.name = "smbus"; + smbus->binding.version = 1; + + smbus->binding.tx = mctp_binding_smbus_tx; + + return smbus; +} |