summaryrefslogtreecommitdiff
path: root/meta-openbmc-mods/meta-common/recipes-core/interfaces
diff options
context:
space:
mode:
Diffstat (limited to 'meta-openbmc-mods/meta-common/recipes-core/interfaces')
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/.clang-format21
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/0001-Smbus-changes-for-libmctp.patch121
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/0002-Fix-Memory-Leak.patch36
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/CMakeLists.txt27
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/asm/rwonce.h89
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/crc32c.c93
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/crc32c.h16
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/libmctp-smbus.h31
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/smbus.c467
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp_git.bb47
10 files changed, 948 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-Smbus-changes-for-libmctp.patch b/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/0001-Smbus-changes-for-libmctp.patch
new file mode 100644
index 000000000..d537b5db7
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/0001-Smbus-changes-for-libmctp.patch
@@ -0,0 +1,121 @@
+From 8e3ae96546010c5d4f3fce6df9c32aece1093458 Mon Sep 17 00:00:00 2001
+From: Nikhil Potade <nikhil.potade@linux.intel.com>
+Date: Tue, 19 Feb 2019 14:16:20 +0800
+Subject: [PATCH 1/1] Smbus changes for libmctp
+
+Signed-off-by: James Feist <james.feist@linux.intel.com>
+
+---
+ core.c | 2 ++
+ libmctp.h | 40 ++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 42 insertions(+)
+
+diff --git a/core.c b/core.c
+index 6e59993..3b11672 100644
+--- a/core.c
++++ b/core.c
+@@ -19,6 +19,7 @@
+
+ /* Internal data structures */
+
++/* clang-format off */
+ struct mctp_bus {
+ mctp_eid_t eid;
+ struct mctp_binding *binding;
+@@ -58,6 +59,7 @@ struct mctp {
+ ROUTE_BRIDGE,
+ } route_policy;
+ };
++/* clang-format on */
+
+ #ifndef BUILD_ASSERT
+ #define BUILD_ASSERT(x) \
+diff --git a/libmctp.h b/libmctp.h
+index 40e5371..766473b 100644
+--- a/libmctp.h
++++ b/libmctp.h
+@@ -19,6 +19,7 @@ typedef uint8_t mctp_eid_t;
+ #define MCTP_EID_BROADCAST 0xff
+
+ /* MCTP packet definitions */
++/* clang-format off */
+ struct mctp_hdr {
+ uint8_t ver;
+ uint8_t dest;
+@@ -34,20 +35,57 @@ struct mctp_hdr {
+ #define MCTP_HDR_SEQ_MASK (0x3)
+ #define MCTP_HDR_TAG_SHIFT (0)
+ #define MCTP_HDR_TAG_MASK (0x7)
++/* clang-format on */
+
+ /* Baseline Transmission Unit and packet size */
+ #define MCTP_BTU 64
+ #define MCTP_PACKET_SIZE(unit) ((unit) + sizeof(struct mctp_hdr))
+ #define MCTP_BODY_SIZE(unit) ((unit) - sizeof(struct mctp_hdr))
+
++#define MCTP_CONTROL_MESSAGE_TYPE 0x00
++
++enum MCTP_COMMAND_CODE {
++ MCTP_COMMAND_CODE_SET_EID = 0x01,
++ MCTP_COMMAND_CODE_GET_EID = 0x02,
++ MCTP_COMMAND_CODE_GET_ENDPOINT_UUID = 0x03,
++ MCTP_COMMAND_CODE_GET_MCTP_VERSION_SUPPORT = 0x04,
++ MCTP_COMMAND_CODE_GET_MESSAGE_TYPE_SUPPORT = 0x05,
++ MCTP_COMMAND_CODE_GET_VENDOR_DEFINED_MSG_SUPPORT= 0x06,
++ MCTP_COMMAND_CODE_RESOLVE_ENDPOINT_ID = 0x07,
++ MCTP_COMMAND_CODE_ALLOCATE_ENDPOINT_IDS = 0x08,
++ MCTP_COMMAND_CODE_ROUTING_INFORMATION_UPDATE = 0x09,
++ MCTP_COMMAND_CODE_GET_ROUTING_TABLE_ENTRIES = 0x0A,
++ MCTP_COMMAND_CODE_PREPARE_FOR_ENDPOINT_DISCOVERY= 0x0B,
++ MCTP_COMMAND_CODE_ENDPOINT_DISCOVERY = 0x0C,
++ MCTP_COMMAND_CODE_DISCOVERY_NOTIFY = 0x0D,
++ MCTP_COMMAND_CODE_GET_NETWORK_ID = 0x0E,
++ MCTP_COMMAND_CODE_QUERY_HOP = 0x0F,
++ MCTP_COMMAND_CODE_RESOLVE_UUID = 0x10,
++ MCTP_COMMAND_CODE_QUERY_RATE_LIMIT = 0x11,
++ MCTP_COMMAND_CODE_REQUEST_TX_RATE_LIMIT = 0x12,
++ MCTP_COMMAND_CODE_UPDATE_RATE_LIMIT = 0x13,
++ MCTP_COMMAND_CODE_QUERY_SUPPORTED_INTERFACES = 0x14
++};
++
++enum MCTP_CONTROL_MSG_COMPLETION_CODE {
++ MCTP_CONTROL_MSG_STATUS_SUCCESS = 0x00,
++ MCTP_CONTROL_MSG_STATUS_ERROR = 0x01,
++ MCTP_CONTROL_MSG_STATUS_ERROR_INVALID_DATA = 0x02,
++ MCTP_CONTROL_MSG_STATUS_ERROR_INVALID_LENGTH = 0x03,
++ MCTP_CONTROL_MSG_STATUS_ERROR_NOT_READY = 0x04,
++ MCTP_CONTROL_MSG_STATUS_ERROR_UNSUPPORTED_CMD = 0x05
++};
++
+ /* packet buffers */
+
++/* clang-format off */
+ struct mctp_pktbuf {
+ size_t start, end, size;
+ size_t mctp_hdr_off;
+ struct mctp_pktbuf *next;
+ unsigned char data[];
+ };
++/* clang-format on */
+
+ struct mctp_binding;
+
+@@ -96,6 +134,7 @@ int mctp_message_tx(struct mctp *mctp, mctp_eid_t eid,
+ void *msg, size_t msg_len);
+
+ /* hardware bindings */
++/* clang-format off */
+ struct mctp_binding {
+ const char *name;
+ uint8_t version;
+@@ -108,6 +147,7 @@ struct mctp_binding {
+ mctp_rx_fn control_rx;
+ void *control_rx_data;
+ };
++/* clang-format on */
+
+ void mctp_binding_set_tx_enabled(struct mctp_binding *binding, bool enable);
+
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/0002-Fix-Memory-Leak.patch b/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/0002-Fix-Memory-Leak.patch
new file mode 100644
index 000000000..52acac1ab
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/0002-Fix-Memory-Leak.patch
@@ -0,0 +1,36 @@
+From bda505bc62f95ee927b75f87c52e04584dab4d79 Mon Sep 17 00:00:00 2001
+From: James Feist <james.feist@linux.intel.com>
+Date: Fri, 26 Jun 2020 13:50:08 -0700
+Subject: [PATCH 1/1] Fix Memory Leak
+
+In mctp_send_tx_queue if rc is of an error,
+the packet does not get freed, causing a leak.
+
+Change-Id: Ic39b0920b454608841e6e879cc028e455520e67d
+Signed-off-by: James Feist <james.feist@linux.intel.com>
+---
+ core.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/core.c b/core.c
+index 6e59993..c251b72 100644
+--- a/core.c
++++ b/core.c
+@@ -543,11 +543,11 @@ static void mctp_send_tx_queue(struct mctp_bus *bus)
+ int rc;
+
+ rc = mctp_packet_tx(bus, pkt);
+- if (rc)
+- break;
+-
+ bus->tx_queue_head = pkt->next;
+ mctp_pktbuf_free(pkt);
++
++ if (rc)
++ break;
+ }
+
+ if (!bus->tx_queue_head)
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/CMakeLists.txt b/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/CMakeLists.txt
new file mode 100644
index 000000000..28354123e
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/CMakeLists.txt
@@ -0,0 +1,27 @@
+cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
+
+add_definitions(-DMCTP_LOG_STDERR)
+add_definitions(-DMCTP_HAVE_FILEIO)
+add_definitions(-DMCTP_HAVE_STDIO)
+add_definitions(-DMCTP_DEFAULT_ALLOC)
+
+add_library(
+ libmctp STATIC alloc.c core.c log.c libmctp.h serial.c smbus.c crc32c.c)
+
+target_include_directories(libmctp
+ PUBLIC
+ $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
+ $<INSTALL_INTERFACE:include/libmctp)
+
+enable_testing()
+
+add_executable(test_eid tests/test_eid.c tests/test-utils.c)
+target_link_libraries(test_eid libmctp)
+
+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 libmctp-smbus.h libmctp-serial.h crc32c.h DESTINATION include)
+
diff --git a/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/asm/rwonce.h b/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/asm/rwonce.h
new file mode 100644
index 000000000..c8beb875d
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/asm/rwonce.h
@@ -0,0 +1,89 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Prevent the compiler from merging or refetching reads or writes. The
+ * compiler is also forbidden from reordering successive instances of
+ * READ_ONCE and WRITE_ONCE, but only when the compiler is aware of some
+ * particular ordering. One way to make the compiler aware of ordering is to
+ * put the two invocations of READ_ONCE or WRITE_ONCE in different C
+ * statements.
+ *
+ * These two macros will also work on aggregate data types like structs or
+ * unions.
+ *
+ * Their two major use cases are: (1) Mediating communication between
+ * process-level code and irq/NMI handlers, all running on the same CPU,
+ * and (2) Ensuring that the compiler does not fold, spindle, or otherwise
+ * mutilate accesses that either do not require ordering or that interact
+ * with an explicit memory barrier or atomic instruction that provides the
+ * required ordering.
+ */
+#ifndef __ASM_GENERIC_RWONCE_H
+#define __ASM_GENERIC_RWONCE_H
+
+#ifndef __ASSEMBLY__
+
+#include <linux/compiler_types.h>
+#include <linux/kasan-checks.h>
+#include <linux/kcsan-checks.h>
+
+/*
+ * Yes, this permits 64-bit accesses on 32-bit architectures. These will
+ * actually be atomic in some cases (namely Armv7 + LPAE), but for others we
+ * rely on the access being split into 2x32-bit accesses for a 32-bit quantity
+ * (e.g. a virtual address) and a strong prevailing wind.
+ */
+#define compiletime_assert_rwonce_type(t) \
+ compiletime_assert(__native_word(t) || sizeof(t) == sizeof(long long), \
+ "Unsupported access size for {READ,WRITE}_ONCE().")
+
+/*
+ * Use __READ_ONCE() instead of READ_ONCE() if you do not require any
+ * atomicity. Note that this may result in tears!
+ */
+#ifndef __READ_ONCE
+#define __READ_ONCE(x) (*(const volatile __unqual_scalar_typeof(x) *)&(x))
+#endif
+
+#define READ_ONCE(x) \
+ ({ \
+ compiletime_assert_rwonce_type(x); \
+ __READ_ONCE(x); \
+ })
+
+#define __WRITE_ONCE(x, val) \
+ do { \
+ *(volatile typeof(x) *)&(x) = (val); \
+ } while (0)
+
+#define WRITE_ONCE(x, val) \
+ do { \
+ compiletime_assert_rwonce_type(x); \
+ __WRITE_ONCE(x, val); \
+ } while (0)
+
+static __always_inline unsigned long __read_once_word_nocheck(const void *addr)
+{
+ return __READ_ONCE(*(unsigned long *)addr);
+}
+
+/*
+ * Use READ_ONCE_NOCHECK() instead of READ_ONCE() if you need to load a
+ * word from memory atomically but without telling KASAN/KCSAN. This is
+ * usually used by unwinding code when walking the stack of a running process.
+ */
+#define READ_ONCE_NOCHECK(x) \
+ ({ \
+ compiletime_assert( \
+ sizeof(x) == sizeof(unsigned long), \
+ "Unsupported access size for READ_ONCE_NOCHECK()."); \
+ (typeof(x)) __read_once_word_nocheck(&(x)); \
+ })
+
+static __always_inline unsigned long read_word_at_a_time(const void *addr)
+{
+ kasan_check_read(addr, 1);
+ return *(unsigned long *)addr;
+}
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ASM_GENERIC_RWONCE_H */
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..4586547e6
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/crc32c.h
@@ -0,0 +1,16 @@
+#ifndef CRC32C_H
+#define CRC32C_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <stdlib.h>
+
+uint32_t crc32c(uint8_t *buf, int len);
+
+#ifdef __cplusplus
+}
+#endif
+#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..67690bcb3
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/libmctp-smbus.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef _LIBMCTP_SMBUS_H
+#define _LIBMCTP_SMBUS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#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);
+void mctp_smbus_free(struct mctp_binding_smbus *smbus);
+int mctp_smbus_open_in_bus(struct mctp_binding_smbus *smbus, int in_bus);
+int mctp_smbus_open_out_bus(struct mctp_binding_smbus *smbus, int out_bus);
+int mctp_smbus_set_in_fd(struct mctp_binding_smbus *smbus, int fd);
+int mctp_smbus_set_out_fd(struct mctp_binding_smbus *smbus, int fd);
+
+#ifdef __cplusplus
+}
+#endif
+#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..2f099a7e5
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/smbus.c
@@ -0,0 +1,467 @@
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifdef MCTP_HAVE_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;
+ 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
+#define SMBUS_COMMAND_CODE_SIZE 1
+#define SMBUS_LENGTH_FIELD_SIZE 1
+#define SMBUS_ADDR_OFFSET_SLAVE 0x1000
+
+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;
+};
+
+#define POLYCHECK (0x1070U << 3)
+static uint8_t crc8_calculate(uint16_t d)
+{
+ int i;
+
+ for (i = 0; i < 8; i++) {
+ if (d & 0x8000) {
+ d = d ^ POLYCHECK;
+ }
+ d = d << 1;
+ }
+
+ return (uint8_t)(d >> 8);
+}
+
+/* Incremental CRC8 over count bytes in the array pointed to by p */
+static uint8_t pec_calculate(uint8_t crc, uint8_t *p, size_t count)
+{
+ int i;
+
+ for (i = 0; i < count; i++) {
+ crc = crc8_calculate((crc ^ p[i]) << 8);
+ }
+
+ return crc;
+}
+
+static uint8_t calculate_pec_byte(uint8_t *buf, size_t len, uint8_t address,
+ uint16_t flags)
+{
+ uint8_t addr = (address << 1) | (flags & I2C_M_RD ? 1 : 0);
+ uint8_t pec = pec_calculate(0, &addr, 1);
+ pec = pec_calculate(pec, buf, len);
+
+ return pec;
+}
+
+static int mctp_smbus_tx(struct mctp_binding_smbus *smbus, uint8_t len)
+{
+
+#ifdef I2C_M_HOLD
+ /* Hold message */
+ static uint16_t holdtimeout = 1000; // timeout in ms.
+ struct i2c_msg msg[2] =
+#else // !I2C_M_HOLD
+ struct i2c_msg msg[1] =
+#endif // I2C_M_HOLD
+ {{.addr = MCTP_SLAVE_ADDRESS,
+ .flags = 0,
+ .len = len,
+ .buf = (__uint8_t *)smbus->txbuf}
+#ifdef I2C_M_HOLD
+ ,
+ {.addr = 0,
+ .flags = I2C_M_HOLD,
+ .len = sizeof(holdtimeout),
+ .buf = (__uint8_t *)&holdtimeout}
+#endif // I2C_M_HOLD
+ };
+
+#ifdef I2C_M_HOLD
+ struct i2c_rdwr_ioctl_data msgrdwr = {&msg, 2};
+#else // !I2C_M_HOLD
+ struct i2c_rdwr_ioctl_data msgrdwr = {&msg, 1};
+#endif // I2C_M_HOLD
+
+ return ioctl(smbus->out_fd, I2C_RDWR, &msgrdwr);
+}
+
+#ifdef I2C_M_HOLD
+static int mctp_smbus_unhold_bus(struct mctp_binding_smbus *smbus)
+{
+ /* Unhold message */
+ static uint16_t holdtimeout = 0; // unhold
+ struct i2c_msg holdmsg = {0, I2C_M_HOLD, sizeof(holdtimeout),
+ (__uint8_t *)&holdtimeout};
+
+ struct i2c_rdwr_ioctl_data msgrdwr = {&holdmsg, 1};
+
+ return ioctl(smbus->out_fd, I2C_RDWR, &msgrdwr);
+}
+#endif // I2C_M_HOLD
+
+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;
+ size_t pkt_length;
+
+ uint8_t i2c_message_buf[256];
+ uint8_t *buf_ptr;
+ uint8_t i2c_message_len;
+
+ uint16_t timeout = 1000;
+
+ /* the length field in the header excludes smbus framing
+ * and escape sequences */
+ pkt_length = mctp_pktbuf_size(pkt);
+
+ buf_ptr = (void *)smbus->txbuf;
+ *buf_ptr = MCTP_COMMAND_CODE;
+ buf_ptr++;
+ *buf_ptr = pkt_length + sizeof(*hdr);
+ buf_ptr++;
+
+ hdr = (void *)buf_ptr;
+ hdr->source_slave_address = MCTP_SOURCE_SLAVE_ADDRESS;
+ buf_ptr = (buf_ptr + sizeof(*hdr));
+ memcpy(buf_ptr, &pkt->data[pkt->start], pkt_length);
+ buf_ptr = buf_ptr + pkt_length;
+
+ uint8_t pec_byte = calculate_pec_byte(
+ smbus->txbuf,
+ SMBUS_COMMAND_CODE_SIZE + SMBUS_LENGTH_FIELD_SIZE + sizeof(*hdr)
+ + pkt_length,
+ MCTP_SLAVE_ADDRESS, 0);
+
+ *buf_ptr = pec_byte;
+
+ i2c_message_len = SMBUS_COMMAND_CODE_SIZE + SMBUS_LENGTH_FIELD_SIZE
+ + sizeof(*hdr) + pkt_length
+ + SMBUS_PEC_BYTE_SIZE; // command code, length,
+ // header, data, pec byte
+
+ if (mctp_smbus_tx(smbus, i2c_message_len)) {
+ mctp_prerr("Can't hold mux");
+ return -1;
+ }
+
+ return 0;
+}
+
+#ifdef MCTP_HAVE_FILEIO
+int mctp_smbus_read(struct mctp_binding_smbus *smbus)
+{
+ ssize_t len = 0;
+ struct mctp_smbus_header_rx *hdr;
+ int ret = 0;
+
+ do {
+ ret = lseek(smbus->in_fd, 0, SEEK_SET);
+ if (ret < 0) {
+ mctp_prerr("Failed to seek");
+ ret = -1;
+ }
+
+ len = read(smbus->in_fd, smbus->rxbuf, sizeof(smbus->rxbuf));
+ if (len < sizeof(*hdr)) {
+ // This condition hits from from time to time, even with
+ // a properly written poll loop, although it's not clear
+ // why. Return an error so that the upper layer can
+ // retry.
+ ret = 0;
+ break;
+ }
+
+ 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);
+ ret = 0;
+ break;
+ }
+ if (hdr->command_code != MCTP_COMMAND_CODE) {
+ mctp_prerr("Got bad command code %d",
+ hdr->command_code);
+ // Not a payload intended for us
+ ret = 0;
+ break;
+ }
+
+ 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));
+ ret = 0;
+ break;
+ }
+
+ if (len < 0) {
+ mctp_prerr("can't read from smbus device: %m");
+ ret = -1;
+ break;
+ }
+
+ smbus->rx_pkt = mctp_pktbuf_alloc(&(smbus->binding), 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");
+ ret = -1;
+ break;
+ }
+
+ mctp_bus_rx(&(smbus->binding), smbus->rx_pkt);
+
+ smbus->rx_pkt = NULL;
+
+ } while (0);
+
+#ifdef I2C_M_HOLD
+ if (mctp_smbus_unhold_bus(smbus)) {
+ mctp_prerr("Can't hold mux");
+ ret = -1;
+ }
+#endif // I2C_M_HOLD
+
+ return ret;
+}
+
+int mctp_smbus_get_in_fd(struct mctp_binding_smbus *smbus)
+{
+ return smbus->in_fd;
+}
+
+
+int mctp_smbus_set_in_fd(struct mctp_binding_smbus *smbus, int fd)
+{
+ smbus->in_fd = fd;
+}
+
+int mctp_smbus_set_out_fd(struct mctp_binding_smbus *smbus, int fd)
+{
+ smbus->out_fd = fd;
+}
+
+int mctp_smbus_get_out_fd(struct mctp_binding_smbus *smbus)
+{
+ return smbus->out_fd;
+}
+
+int mctp_smbus_open_in_bus(struct mctp_binding_smbus *smbus, int in_bus)
+{
+ char filename[60];
+ size_t filename_size = 0;
+ char slave_mqueue[20];
+ size_t mqueue_size = 0;
+ int fd = 0;
+ size_t size = sizeof(filename);
+ int address_7_bit = MCTP_SOURCE_SLAVE_ADDRESS >> 1;
+ int ret = -1;
+
+ snprintf(filename, size,
+ "/sys/bus/i2c/devices/i2c-%d/%d-%04x/slave-mqueue", in_bus,
+ in_bus, SMBUS_ADDR_OFFSET_SLAVE | address_7_bit);
+
+ ret = open(filename, O_RDONLY | O_NONBLOCK | O_CLOEXEC);
+ if (ret >= 0) {
+ return ret;
+ }
+
+ // Device doesn't exist. Create it.
+ filename_size = sizeof(filename);
+ snprintf(filename, filename_size,
+ "/sys/bus/i2c/devices/i2c-%d/new_device", in_bus);
+ 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",
+ SMBUS_ADDR_OFFSET_SLAVE | 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", in_bus,
+ in_bus, SMBUS_ADDR_OFFSET_SLAVE | address_7_bit);
+
+ return open(filename, O_RDONLY | O_NONBLOCK | O_CLOEXEC);
+}
+
+int mctp_smbus_open_out_bus(struct mctp_binding_smbus *smbus, int out_bus)
+{
+ char filename[60];
+ size_t size = sizeof(filename);
+ snprintf(filename, size, "/dev/i2c-%d", out_bus);
+ filename[size - 1] = '\0';
+
+ return open(filename, O_RDWR | O_NONBLOCK);
+}
+
+/*
+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 = 0;
+ char slave_mqueue[20];
+ size_t mqueue_size = 0;
+ int fd = 0;
+ size_t size = sizeof(filename);
+ int address_7_bit = MCTP_SOURCE_SLAVE_ADDRESS >> 1;
+
+ snprintf(filename, size,
+ "/sys/bus/i2c/devices/i2c-%d/%d-%04x/slave-mqueue",
+ root_bus_num, root_bus_num,
+ SMBUS_ADDR_OFFSET_SLAVE | 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",
+ SMBUS_ADDR_OFFSET_SLAVE | 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,
+ SMBUS_ADDR_OFFSET_SLAVE | 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)
+{
+ smbus->bus_id = mctp_register_bus(mctp, &smbus->binding, eid);
+ mctp_binding_set_tx_enabled(&smbus->binding, true);
+}
+
+struct mctp_binding_smbus *mctp_smbus_init(void)
+{
+ struct mctp_binding_smbus *smbus;
+
+ smbus = __mctp_alloc(sizeof(*smbus));
+ memset(&(smbus->binding), 0, sizeof(smbus->binding));
+
+ smbus->in_fd = -1;
+ smbus->out_fd = -1;
+
+ smbus->rx_pkt = NULL;
+ smbus->binding.name = "smbus";
+ smbus->binding.version = 1;
+ smbus->binding.pkt_size = sizeof(smbus->rxbuf);
+
+ smbus->binding.tx = mctp_binding_smbus_tx;
+ return smbus;
+}
+
+void mctp_smbus_free(struct mctp_binding_smbus *smbus)
+{
+ __mctp_free(smbus);
+}
diff --git a/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp_git.bb b/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp_git.bb
new file mode 100644
index 000000000..eba56f829
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp_git.bb
@@ -0,0 +1,47 @@
+SUMMARY = "libmctp"
+DESCRIPTION = "Implementation of MCTP (DTMF DSP0236)"
+
+SRC_URI = "git://github.com/openbmc/libmctp.git"
+SRCREV = "663ec39ea107c2a736f9bcb20cbfdfa623092ab1"
+
+PV = "0.1+git${SRCPV}"
+
+LICENSE = "Apache-2.0 | GPLv2"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=0d30807bb7a4f16d36e96b78f9ed8fae"
+
+inherit cmake
+
+S = "${WORKDIR}/git"
+
+DEPENDS += "i2c-tools"
+
+FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
+
+SRC_URI += "file://0001-Smbus-changes-for-libmctp.patch \
+ file://0002-Fix-Memory-Leak.patch \
+ file://CMakeLists.txt \
+ file://crc32c.c \
+ file://crc32c.h \
+ file://libmctp-smbus.h \
+ file://smbus.c"
+
+do_configure:prepend() {
+ cp -f ${WORKDIR}/*.c ${S}
+ cp -f ${WORKDIR}/*.h ${S}
+ cp -f ${WORKDIR}/CMakeLists.txt ${S}
+}
+
+# linux-libc-headers guides this way to include custom uapi headers
+CFLAGS:append = " -I ${STAGING_KERNEL_DIR}/include/uapi"
+CFLAGS:append = " -I ${STAGING_KERNEL_DIR}/include"
+CXXFLAGS:append = " -I ${STAGING_KERNEL_DIR}/include/uapi"
+CXXFLAGS:append = " -I ${STAGING_KERNEL_DIR}/include"
+
+do_configure[depends] += "virtual/kernel:do_shared_workdir"
+
+# Copying the depricated header from kernel as a temporary fix to resolve build breaks.
+# It should be removed later after fixing the header dependency in this repository.
+SRC_URI += "file://asm/rwonce.h"
+do_configure:prepend() {
+ cp -r ${WORKDIR}/asm ${S}/asm
+}