freeipmi-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Freeipmi-devel] [PATCH] Using DMI firmware in sysfs if exists


From: Ike Panhc
Subject: [Freeipmi-devel] [PATCH] Using DMI firmware in sysfs if exists
Date: Tue, 27 Jun 2017 16:07:40 +0800

On arm64 system scanning /dev/mem for SMBIOS tables might fail and
stopped with SIGBUS. Kernel version > 4.2 provides DMI tables in
/sys/firmware/dmi/tables and it is much safer for ipmi-locate to
read. If it exists, reading from it instead of /dev/mem fix
ipmi-locate crash on several arm64 system.

Unfortunately mmap() does not work on DMI tables so also fallback to
read if mmap() failed.

Signed-off-by: Ike Panhc <address@hidden>
---
 libfreeipmi/locate/ipmi-locate-dmidecode.c | 28 +++++++++++++++++++++++-----
 1 file changed, 23 insertions(+), 5 deletions(-)

diff --git a/libfreeipmi/locate/ipmi-locate-dmidecode.c 
b/libfreeipmi/locate/ipmi-locate-dmidecode.c
index 8a89fc0..db1c473 100644
--- a/libfreeipmi/locate/ipmi-locate-dmidecode.c
+++ b/libfreeipmi/locate/ipmi-locate-dmidecode.c
@@ -115,7 +115,6 @@ struct dmi_header
   fipmiu16 handle;
 };
 
-#ifndef HAVE_MMAP
 static int
 _myread (ipmi_locate_ctx_t ctx,
          int fd,
@@ -155,7 +154,6 @@ _myread (ipmi_locate_ctx_t ctx,
 
   return (0);
 }
-#endif
 
 static int
 _checksum (const fipmiu8 *buf, size_t len)
@@ -233,14 +231,16 @@ _mem_chunk (ipmi_locate_ctx_t ctx,
                    base - mmoffset)) == MAP_FAILED)
     {
       LOCATE_ERRNO_TO_LOCATE_ERRNUM (ctx, errno);
-      goto cleanup;
+      goto try_read;
     }
 
   memcpy (p, (fipmiu8 *) mmp + mmoffset, len);
   rv = p;
   /* ignore potential error, just return result */
   munmap (mmp, mmoffset + len);
-#else /* HAVE_MMAP */
+  goto cleanup;
+ try_read:
+#endif /* HAVE_MMAP */
 
   if (lseek (fd, base, SEEK_SET) < 0)
     {
@@ -252,7 +252,6 @@ _mem_chunk (ipmi_locate_ctx_t ctx,
     goto cleanup;
 
   rv = p;
-#endif /* HAVE_MMAP */
 
  cleanup:
   /* ignore potential error, cleanup path */
@@ -457,6 +456,8 @@ ipmi_locate_dmidecode_get_device_info (ipmi_locate_ctx_t 
ctx,
   char linebuf[64];
   fipmiu8 *buf = NULL;
   int rv = -1;
+  static char const sys_fw_dmi_tables[] = "/sys/firmware/dmi/tables/DMI";
+  struct stat st;
 
   if (!ctx || ctx->magic != IPMI_LOCATE_CTX_MAGIC)
     {
@@ -471,6 +472,23 @@ ipmi_locate_dmidecode_get_device_info (ipmi_locate_ctx_t 
ctx,
     }
 
   memset (&locate_info, '\0', sizeof (struct ipmi_locate_info));
+
+  /* if DMI firmware exist, use it and do not dig into /dev/mem */
+  if (!(stat (sys_fw_dmi_tables, &st)))
+    {
+      rv = _dmi_table (ctx,
+                        0,
+                        st.st_size,
+                        st.st_size / 4,
+                        0,
+                        sys_fw_dmi_tables,
+                        type,
+                        &locate_info);
+      if (!(rv))
+        memcpy (info, &locate_info, sizeof (struct ipmi_locate_info));
+      return (rv);
+    }
+
   /*
    * Linux up to 2.6.6-rc2: /proc/efi/systab
    * Linux 2.6.6-rc3 and up: /sys/firmware/efi/systab
-- 
2.7.4




reply via email to

[Prev in Thread] Current Thread [Next in Thread]