dmi: Adding IPMI detection
authorErwan Velu <erwan.velu@free.fr>
Sun, 22 Mar 2009 08:23:15 +0000 (09:23 +0100)
committerErwan Velu <erwan.velu@free.fr>
Thu, 26 Mar 2009 17:25:48 +0000 (18:25 +0100)
Impact: IPMI base board can now be detected

Detecting IPMI via DMI structures

com32/gplinclude/dmi/dmi.h
com32/gplinclude/dmi/dmi_ipmi.h [new file with mode: 0644]
com32/gpllib/Makefile
com32/gpllib/dmi/dmi.c
com32/gpllib/dmi/dmi_ipmi.c [new file with mode: 0644]

index 924ed42..89782a9 100644 (file)
 
 #define PAGE_SIZE 4096
 
-/*typedef struct {
-        uint32_t l;
-        uint32_t h;
-} uint64_t;*/
-
 extern const char *out_of_spec;
 extern const char *bad_index;
 
@@ -38,6 +33,7 @@ enum {DMI_TABLE_PRESENT = 100, ENODMITABLE};
 #include "dmi_processor.h"
 #include "dmi_memory.h"
 #include "dmi_battery.h"
+#include "dmi_ipmi.h"
 
 extern char display_line;
 #define moreprintf(...) do { display_line++; if (display_line == 24) { char tempbuf[10]; display_line=0; printf("Press enter to continue"); fgets(tempbuf, sizeof tempbuf, stdin);}  printf ( __VA_ARGS__); } while (0);
@@ -69,6 +65,7 @@ typedef struct {
         s_processor processor;
         s_battery battery;
         s_memory memory[MAX_DMI_MEMORY_ITEMS];
+        s_ipmi ipmi;
         int memory_count;
         dmi_table dmitable;
 } s_dmi;
diff --git a/com32/gplinclude/dmi/dmi_ipmi.h b/com32/gplinclude/dmi/dmi_ipmi.h
new file mode 100644 (file)
index 0000000..7dcb71b
--- /dev/null
@@ -0,0 +1,33 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2006-2009 Erwan Velu - 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, Inc., 53 Temple Place Ste 330,
+ *   Boston MA 02111-1307, USA; either version 2 of the License, or
+ *   (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+#ifndef DMI_IPMI_H
+#define DMI_IPMI_H
+
+#define IPMI_INTERFACE_TYPE_SIZE       32
+#define IPMI_MEMORY_MODEL_SIZE         16
+
+typedef struct {
+char interface_type[IPMI_INTERFACE_TYPE_SIZE];
+uint8_t  major_specification_version;
+uint8_t  minor_specification_version;
+uint8_t I2C_slave_address;
+uint16_t nv_address;
+uint64_t base_address;
+
+uint8_t  irq;
+bool filled;
+} s_ipmi;
+
+void dmi_ipmi_base_address(uint8_t type, const uint8_t *p, s_ipmi *ipmi);
+const char *dmi_ipmi_interface_type(uint8_t code);
+#endif
index 08164c2..46ed42e 100644 (file)
@@ -10,7 +10,7 @@ REQFLAGS += -I../gplinclude
 
 LIBOBJS  = dmi/dmi_battery.o dmi/dmi_chassis.o dmi/dmi_memory.o            \
            dmi/dmi_processor.o dmi/dmi.o dmi/dmi_bios.o dmi/dmi_base_board.o \
-          cpuid.o
+          dmi/dmi_ipmi.o cpuid.o
 
 BINDIR   = /usr/bin
 LIBDIR   = /usr/lib
index a2a08b5..23caa33 100644 (file)
@@ -553,8 +553,26 @@ void dmi_decode(struct dmi_header *h, uint16_t ver, s_dmi *dmi)
 
                //      sprintf(dmi->battery.oem_info,"0x%08X",DWORD(h, data+0x16));
                         break;
-
-
+             case 38: /* 3.3.39 IPMI Device Information */
+                        if (h->length < 0x10) break;
+                       dmi->ipmi.filled=true;
+                       snprintf(dmi->ipmi.interface_type,sizeof(dmi->ipmi.interface_type),
+                               "%s", dmi_ipmi_interface_type(data[0x04]));
+                       dmi->ipmi.major_specification_version=data[0x05] >> 4;
+                       dmi->ipmi.minor_specification_version=data[0x05] & 0x0F;
+                       dmi->ipmi.I2C_slave_address=data[0x06] >> 1;
+                        if (data[0x07] != 0xFF)
+                               dmi->ipmi.nv_address=data[0x07];
+                        else
+                               dmi->ipmi.nv_address=0; /* Not Present */
+                        dmi_ipmi_base_address(data[0x04], data + 0x08,
+                                &dmi->ipmi);
+                        if (h->length < 0x12) break;
+                       if (data[0x11] != 0x00)
+                        {
+                                dmi->ipmi.irq=data[0x11];
+                        }
+                        break;
         }
 }
 
diff --git a/com32/gpllib/dmi/dmi_ipmi.c b/com32/gpllib/dmi/dmi_ipmi.c
new file mode 100644 (file)
index 0000000..8ea5f79
--- /dev/null
@@ -0,0 +1,59 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Portions of this file taken from the dmidecode project
+ *
+ *   Copyright (C) 2000-2002 Alan Cox <alan@redhat.com>
+ *   Copyright (C) 2002-2008 Jean Delvare <khali@linux-fr.org>
+ *
+ *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ *   For the avoidance of doubt the "preferred form" of this code is one which
+ *   is in an open unpatent encumbered format. Where cryptographic key signing
+ *   forms part of the process of creating an executable the information
+ *   including keys needed to generate an equivalently functional executable
+ *   are deemed to be part of the source code.
+*/
+
+#include <dmi/dmi.h>
+#include <stdio.h>
+
+const char *dmi_ipmi_interface_type(uint8_t code)
+{
+        /* 3.3.39.1 and IPMI 2.0, appendix C1, table C1-2 */
+        static const char *type[] = {
+                "Unknown", /* 0x00 */
+                "KCS (Keyboard Control Style)",
+                "SMIC (Server Management Interface Chip)",
+                "BT (Block Transfer)",
+                "SSIF (SMBus System Interface)" /* 0x04 */
+        };
+
+        if (code <= 0x04)
+                return type[code];
+        return out_of_spec;
+}
+
+void dmi_ipmi_base_address(uint8_t type, const uint8_t *p, s_ipmi *ipmi)
+{
+        if (type == 0x04) /* SSIF */
+        {
+                ipmi->base_address= (*p) >> 1;
+        }
+        else
+        {
+                ipmi->base_address = QWORD(p);
+        }
+}
+