From: Christian Kohn <chris.k...@amd.com>

The supported Xilinx OEM FRU records are MAC_ID and FREE_FORM. This FRU OEM
extension parses these records and prints them with proper formatting.

To use this feature, run the ipmi-fru command as follows:
$ sudo ./ipmi-fru 
--fru-file=/sys/devices/platform/axi/ff030000.i2c/i2c-1/1-0051/eeprom \
  --interpret-oem-data

Note: The EEPROM address can vary between different platforms. This is just an
      example.

This feature has been tested with the Xilinx Kria KV260 and KR260 Starter Kits.

Signed-off-by: Christian Kohn <chris.k...@amd.com>
---
 ipmi-fru/Makefile.am                          |   2 +
 ipmi-fru/ipmi-fru-oem-xilinx.c                | 171 ++++++++++++++++++
 ipmi-fru/ipmi-fru-oem-xilinx.h                |  33 ++++
 ipmi-fru/ipmi-fru-output.c                    |  14 ++
 libfreeipmi/include/freeipmi/freeipmi.h.in    |   1 +
 .../oem/ipmi-fru-xilinx-oem-record-format.h   |  45 +++++
 .../spec/ipmi-iana-enterprise-numbers-spec.h  |   1 +
 7 files changed, 267 insertions(+)
 create mode 100644 ipmi-fru/ipmi-fru-oem-xilinx.c
 create mode 100644 ipmi-fru/ipmi-fru-oem-xilinx.h
 create mode 100644 
libfreeipmi/include/freeipmi/record-format/oem/ipmi-fru-xilinx-oem-record-format.h

diff --git a/ipmi-fru/Makefile.am b/ipmi-fru/Makefile.am
index d0a0a3902..57c8592eb 100644
--- a/ipmi-fru/Makefile.am
+++ b/ipmi-fru/Makefile.am
@@ -24,6 +24,8 @@ ipmi_fru_SOURCES = \
        ipmi-fru-argp.h \
        ipmi-fru-oem-wistron.c \
        ipmi-fru-oem-wistron.h \
+       ipmi-fru-oem-xilinx.c \
+       ipmi-fru-oem-xilinx.h \
        ipmi-fru-output.c \
        ipmi-fru-output.h
 
diff --git a/ipmi-fru/ipmi-fru-oem-xilinx.c b/ipmi-fru/ipmi-fru-oem-xilinx.c
new file mode 100644
index 000000000..87bb18f00
--- /dev/null
+++ b/ipmi-fru/ipmi-fru-oem-xilinx.c
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2022, Advanced Micro Devices, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+#include <stdio.h>
+#include <stdlib.h>
+#if STDC_HEADERS
+#include <string.h>
+#endif /* STDC_HEADERS */
+#include <assert.h>
+
+#include <freeipmi/freeipmi.h>
+
+#include "ipmi-fru_.h"
+#include "ipmi-fru-oem-xilinx.h"
+
+#include "freeipmi-portability.h"
+
+static char *
+_version_str (uint8_t version)
+{
+  switch (version)
+    {
+    case IPMI_FRU_OEM_XILINX_MAC_ID_VERSION_BOARD:
+      return "Board";
+    case IPMI_FRU_OEM_XILINX_MAC_ID_VERSION_SYSCTL:
+      return "System Controller";
+    case IPMI_FRU_OEM_XILINX_MAC_ID_VERSION_MODULE:
+      return "Module";
+    case IPMI_FRU_OEM_XILINX_MAC_ID_VERSION_DUT_MAC:
+      return "DUT - MAC";
+    case IPMI_FRU_OEM_XILINX_MAC_ID_VERSION_DUT_ETHERCAT:
+      return "DUT - EtherCAT";
+    default:
+      return "";
+    }
+
+  return (NULL);                /* NOT REACHED */
+}
+
+int
+ipmi_fru_oem_xilinx_oem_record (ipmi_fru_state_data_t *state_data,
+                                uint8_t record_type_id,
+                                uint32_t manufacturer_id,
+                                uint8_t *oem_data,
+                                unsigned int oem_data_len)
+{
+  assert (state_data);
+  assert (manufacturer_id == IPMI_IANA_ENTERPRISE_ID_XILINX);
+  assert (oem_data);
+
+  /* The MAC_ID record type ID is 0xD2. The MAC ID record consists of a 1 byte
+   * version ID followed by one or more 6-byte MAC addresses. If the MAC ID
+   * version is set to "DUT - EtherCAT", a 4-byte EtherCAT ID is used instead 
of
+   * a 6-byte MAC address.
+   */
+  if (record_type_id == IPMI_FRU_OEM_XILINX_MAC_ID && oem_data_len)
+    {
+      uint8_t version = oem_data[0];
+      unsigned int len = oem_data_len - 1;
+
+      pstdout_printf (state_data->pstate,
+                      "  FRU OEM MAC Version: %s (%xh)\n",
+                      _version_str(version),
+                      version);
+
+      /* The MAC_ID record can hold multiple MAC addresses that are 6 bytes 
long
+       * each if version is set to 0x31.
+       */
+      if ((version == IPMI_FRU_OEM_XILINX_MAC_ID_VERSION_BOARD ||
+           version == IPMI_FRU_OEM_XILINX_MAC_ID_VERSION_SYSCTL ||
+           version == IPMI_FRU_OEM_XILINX_MAC_ID_VERSION_MODULE ||
+           version == IPMI_FRU_OEM_XILINX_MAC_ID_VERSION_DUT_MAC ) &&
+          (len % 6) == 0)
+        {
+          unsigned int i, j, start, stop;
+          unsigned int mac_cnt = len / 6;
+
+          for (j = 0; j < mac_cnt; j++)
+            {
+              pstdout_printf (state_data->pstate, "  FRU OEM MAC ID %d: ", j);
+
+              start = j*6 + 1;
+              stop = start + 5;
+
+              for (i = start; i < stop; i++)
+                {
+                  pstdout_printf (state_data->pstate, "%02x:", oem_data[i]);
+                }
+
+              pstdout_printf (state_data->pstate, "%02x\n", oem_data[i]);
+            }
+
+          return (1);
+        }
+
+      /* The MAC_ID record holds one EtherCAT ID that is 4 bytes long if 
version
+       * is set to 0x32. The assigned EtherCAT ID for Xilinx is 0x0000056F.
+       */
+      if (version == IPMI_FRU_OEM_XILINX_MAC_ID_VERSION_DUT_ETHERCAT &&
+          len == 4)
+        {
+          pstdout_printf (state_data->pstate, "  FRU OEM EtherCAT ID: 0x");
+
+          for (unsigned int i = 1; i < len+1; i++)
+            {
+              pstdout_printf (state_data->pstate, "%02X", oem_data[i]);
+            }
+
+          pstdout_printf (state_data->pstate, "\n");
+
+          return (1);
+        }
+    }
+
+  /* The free form data record type ID is 0xD3. It consists of one or more
+   * fields where each field is split into N byte identifier and M byte data
+   * followed by a 0x00 end of field delimiter. The below code parses the free
+   * form record and prints each field on a new line prefixed with 'FRU OEM '.
+   */
+  if (record_type_id == IPMI_FRU_OEM_XILINX_FREE_FORM && oem_data_len)
+    {
+      unsigned int i;
+      unsigned int new_field = 1;
+
+      for (i = 0; i < oem_data_len; i++)
+        {
+          /* 0x00 marks the end of the field */
+          if (oem_data[i] == 0)
+            {
+              if (new_field == 0)
+                {
+                  pstdout_printf (state_data->pstate, "\n");
+                }
+              new_field = 1;
+              continue;
+            }
+
+          /* Start of a new field */
+          if (new_field == 1)
+            {
+              new_field = 0;
+              pstdout_printf (state_data->pstate, "  FRU OEM ");
+            }
+
+          pstdout_printf (state_data->pstate, "%c", oem_data[i]);
+        }
+
+      return (1);
+    }
+
+  return (0);
+}
diff --git a/ipmi-fru/ipmi-fru-oem-xilinx.h b/ipmi-fru/ipmi-fru-oem-xilinx.h
new file mode 100644
index 000000000..2484cd515
--- /dev/null
+++ b/ipmi-fru/ipmi-fru-oem-xilinx.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2022, Advanced Micro Devices, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef IPMI_FRU_OEM_XILINX_H
+#define IPMI_FRU_OEM_XILINX_H
+
+#include <freeipmi/freeipmi.h>
+
+#include "ipmi-fru_.h"
+
+/* Returns 1 on interpretation, 0 if not, -1 on error */
+int ipmi_fru_oem_xilinx_oem_record (ipmi_fru_state_data_t *state_data,
+                                    uint8_t record_type_id,
+                                    uint32_t manufacturer_id,
+                                    uint8_t *oem_data,
+                                    unsigned int oem_data_len);
+
+#endif /* IPMI_FRU_OEM_XILINX_H */
diff --git a/ipmi-fru/ipmi-fru-output.c b/ipmi-fru/ipmi-fru-output.c
index 845971018..d29c4470e 100644
--- a/ipmi-fru/ipmi-fru-output.c
+++ b/ipmi-fru/ipmi-fru-output.c
@@ -51,6 +51,7 @@
 #include "ipmi-fru_.h"
 #include "ipmi-fru-output.h"
 #include "ipmi-fru-oem-wistron.h"
+#include "ipmi-fru-oem-xilinx.h"
 #include "tool-util-common.h"
 
 #include "freeipmi-portability.h"
@@ -1201,6 +1202,19 @@ ipmi_fru_output_oem_record (ipmi_fru_state_data_t 
*state_data,
           if (ret)
             return (0);
         }
+
+      if (manufacturer_id == IPMI_IANA_ENTERPRISE_ID_XILINX)
+        {
+          if ((ret = ipmi_fru_oem_xilinx_oem_record (state_data,
+                                                     record_type_id,
+                                                     manufacturer_id,
+                                                     oem_data,
+                                                     oem_data_len)) < 0)
+            return (-1);
+
+          if (ret)
+            return (0);
+        }
     }
 
   if (oem_data_len)
diff --git a/libfreeipmi/include/freeipmi/freeipmi.h.in 
b/libfreeipmi/include/freeipmi/freeipmi.h.in
index a03178e97..fbd6749e9 100644
--- a/libfreeipmi/include/freeipmi/freeipmi.h.in
+++ b/libfreeipmi/include/freeipmi/freeipmi.h.in
@@ -82,6 +82,7 @@ extern "C" {
 #include <freeipmi/record-format/ipmi-sdr-record-format.h>
 #include <freeipmi/record-format/ipmi-sel-record-format.h>
 #include <freeipmi/record-format/oem/ipmi-fru-wistron-oem-record-format.h>
+#include <freeipmi/record-format/oem/ipmi-fru-xilinx-oem-record-format.h>
 #include 
<freeipmi/record-format/oem/ipmi-sdr-oem-intel-node-manager-record-format.h>
 #include <freeipmi/record-format/oem/ipmi-sdr-oem-intel-record-format.h>
 #include <freeipmi/record-format/oem/ipmi-sel-oem-intel-record-format.h>
diff --git 
a/libfreeipmi/include/freeipmi/record-format/oem/ipmi-fru-xilinx-oem-record-format.h
 
b/libfreeipmi/include/freeipmi/record-format/oem/ipmi-fru-xilinx-oem-record-format.h
new file mode 100644
index 000000000..434e2031a
--- /dev/null
+++ 
b/libfreeipmi/include/freeipmi/record-format/oem/ipmi-fru-xilinx-oem-record-format.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2022, Advanced Micro Devices, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef IPMI_FRU_OEM_XILINX_RECORD_FORMAT_H
+#define IPMI_FRU_OEM_XILINX_RECORD_FORMAT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <freeipmi/fiid/fiid.h>
+
+/* OEM multi-record IDs used by Xilinx */
+#define IPMI_FRU_OEM_XILINX_THERMAL   0xD0
+#define IPMI_FRU_OEM_XILINX_POWER     0xD1
+#define IPMI_FRU_OEM_XILINX_MAC_ID    0xD2
+#define IPMI_FRU_OEM_XILINX_FREE_FORM 0xD3
+
+/* OEM MAC ID versions used by Xilinx */
+#define IPMI_FRU_OEM_XILINX_MAC_ID_VERSION_BOARD        0x01
+#define IPMI_FRU_OEM_XILINX_MAC_ID_VERSION_SYSCTL       0x11
+#define IPMI_FRU_OEM_XILINX_MAC_ID_VERSION_MODULE       0x21
+#define IPMI_FRU_OEM_XILINX_MAC_ID_VERSION_DUT_MAC      0x31
+#define IPMI_FRU_OEM_XILINX_MAC_ID_VERSION_DUT_ETHERCAT 0x32
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* IPMI_FRU_OEM_XILINX_RECORD_FORMAT_H */
diff --git 
a/libfreeipmi/include/freeipmi/spec/ipmi-iana-enterprise-numbers-spec.h 
b/libfreeipmi/include/freeipmi/spec/ipmi-iana-enterprise-numbers-spec.h
index d286f33a4..4c24b5259 100644
--- a/libfreeipmi/include/freeipmi/spec/ipmi-iana-enterprise-numbers-spec.h
+++ b/libfreeipmi/include/freeipmi/spec/ipmi-iana-enterprise-numbers-spec.h
@@ -29,6 +29,7 @@ extern "C" {
 #define IPMI_IANA_ENTERPRISE_ID_SUN_MICROSYSTEMS         42
 #define IPMI_IANA_ENTERPRISE_ID_INTEL                   343
 #define IPMI_IANA_ENTERPRISE_ID_DELL                    674
+#define IPMI_IANA_ENTERPRISE_ID_XILINX                 4314
 #define IPMI_IANA_ENTERPRISE_ID_MAGNUM_TECHNOLOGIES    5593
 #define IPMI_IANA_ENTERPRISE_ID_QUANTA                 7244
 #define IPMI_IANA_ENTERPRISE_ID_FUJITSU               10368
-- 
2.17.1


Reply via email to