Cress, Andrew R wrote:
Corey,

I ran into a case that required ipmi_imb and CONFIG_COMPAT, and ipmi_imb
did not previously support it, so I have attached the updated source
with those changes. I included the source files since they are created by the patch anyway. Any comments? Could a form of this get merged in for the next driver version? Andy
Well, patches are still really appreciated as they are easier to review.

This patch has a lot of problems; it will really only work on older kernels and will definitely not work on current kernels. The compat stuff has changed a lot (and devfs is not longer there and you can no longer include config.h, among other things).

Does the change really need to have all the backwards compatibility changes?

I'm attaching the patch, BTW.

-corey

Index: linux-2.6.24/drivers/char/ipmi/ipmi_imb.c
===================================================================
--- linux-2.6.24.orig/drivers/char/ipmi/ipmi_imb.c
+++ linux-2.6.24/drivers/char/ipmi/ipmi_imb.c
@@ -31,6 +31,7 @@
  *  675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/errno.h>
@@ -39,13 +40,13 @@
 #include <linux/poll.h>
 #include <linux/spinlock.h>
 #include <linux/slab.h>
+#include <linux/devfs_fs_kernel.h>
 #include <linux/ipmi.h>
 #include <linux/ipmi_imb.h>
 #include <linux/init.h>
-#include <linux/mm.h>
+#include <linux/version.h>
 
-
-#define IPMI_IMB_VERSION   "v34"
+#define IPMI_IMB_VERSION   "v36"
 #define MAX_BUFFER_SIZE                 64
 #define BMC_SA				0x20
 
@@ -139,8 +140,11 @@ static void imb_msg_recv(struct ipmi_rec
 			}
 		}
 		if (msg) {
-//			printk(KERN_INFO "imb_msg_recv: DROPPING netfn %x/cmd %x/type %x/channel %x/msgid %ld\n",
-//						msg->msg.netfn, msg->msg.cmd, msg->addr.addr_type, msg->addr.channel, msg->msgid);
+#ifdef DEBUG
+			printk(KERN_INFO "imb_msg_recv: DROPPING netfn %x/cmd %x/type %x/channel %x/msgid %ld\n",
+				msg->msg.netfn, msg->msg.cmd, msg->addr.
+				addr_type, msg->addr.channel, msg->msgid);
+#endif
 			/* No waiter found, this was either a "don't
 			 * wait for the response" message or the
 			 * waiter was interrupted. */
@@ -258,19 +262,18 @@ ipmb_checksum(unsigned char *data, int s
 
 extern void ipmi_delayed_shutdown(long delay, int power_off);
 
-static int ipmi_imb_ioctl(struct inode  *inode,
-			  struct file   *file,
+static int ipmi_imb_ioctl_cmd( struct file   *file,
 			  unsigned int  cmd,
-			  unsigned long data)
+			  struct smi *smi,
+			  int fcompat)
 {
 	struct priv_data *priv = file->private_data;
 	int              rv = -EINVAL;
-	struct smi       smi;
 	unsigned long    flags;
+	unsigned int     sz;
 
-	if (copy_from_user((caddr_t)&smi, (caddr_t)data, sizeof(smi))) {
-		return -EFAULT;
-	}
+	if (fcompat) sz = sizeof(int); /*(4)*/
+	else sz = sizeof(long); /*(8)*/
 
 	switch(cmd) {
 	case IOCTL_IMB_POLL_ASYNC:
@@ -291,12 +294,12 @@ static int ipmi_imb_ioctl(struct inode  
 		ImbAsyncResponse     *pAsyncResp = (ImbAsyncResponse *) resp;
 		unsigned long        length = 0;
 
-		if (smi.cbInBuffer < sizeof(ImbAsyncRequest))
+		if (smi->cbInBuffer < sizeof(ImbAsyncRequest))
 			return -EINVAL;
-		if (smi.cbOutBuffer < MIN_ASYNC_RESP_SIZE)
+		if (smi->cbOutBuffer < MIN_ASYNC_RESP_SIZE)
 			return -EINVAL;
 
-		if (copy_from_user( pAsyncReq, smi.lpvInBuffer,
+		if (copy_from_user( pAsyncReq, smi->lpvInBuffer,
 					sizeof(ImbAsyncRequest)) == -1) {
 			return(-EFAULT);
 		}
@@ -416,15 +419,13 @@ static int ipmi_imb_ioctl(struct inode  
 				length += sizeof(pAsyncResp->thisSeq) + 1;
 			}
 
-			if (copy_to_user(smi.lpvOutBuffer, pAsyncResp, length))
+			if (copy_to_user(smi->lpvOutBuffer, pAsyncResp, length))
 			{
 				return -EFAULT;
 			}
 			rv = STATUS_SUCCESS;
 		}
-		if (copy_to_user(smi.lpcbBytesReturned,
-				 &length,
-				 sizeof(length)))
+		if (copy_to_user(smi->lpcbBytesReturned, &length, sz))
 		{
 			return -EFAULT;
 		}
@@ -438,7 +439,11 @@ static int ipmi_imb_ioctl(struct inode  
 		ImbRequestBuffer     *pImbReq=(ImbRequestBuffer *)imbReqBuffer;
 		ImbResponseBuffer    *pImbResp=(ImbResponseBuffer*)imbRespBuffer;
 		struct ipmi_addr     addr;
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10))
+		struct ipmi_msg msg;
+#else
 		struct kernel_ipmi_msg msg;
+#endif
 		unsigned long        msgid = 0;
 		     unsigned char    source_address = 0;
 		     unsigned char    source_lun = 0;
@@ -447,23 +452,25 @@ static int ipmi_imb_ioctl(struct inode  
 		wait_queue_t         wait;
 		struct waiting_rsp   waiter;
 
-
-		if ((smi.cbInBuffer < MIN_IMB_REQ_BUF_SIZE)
-		    || (smi.cbOutBuffer < MIN_IMB_RESP_BUF_SIZE))
+		if ((smi->cbInBuffer < MIN_IMB_REQ_BUF_SIZE)
+		    || (smi->cbOutBuffer < MIN_IMB_RESP_BUF_SIZE))
 		{
+			printk(KERN_ERR "imb_ioctl: Buffer length too short\n");
 			return -EINVAL;
 		}
 
-		if (smi.cbInBuffer > MAX_BUFFER_SIZE) {
+		if (smi->cbInBuffer > MAX_BUFFER_SIZE) {
 			/* Input buffer is too large */
+			printk(KERN_ERR "imb_ioctl: Input buffer too large\n");
 			return -EINVAL;
 		}
 
-		if (copy_from_user(pImbReq, smi.lpvInBuffer, smi.cbInBuffer)) {
+		if (copy_from_user(pImbReq,smi->lpvInBuffer,smi->cbInBuffer)) {
+			printk(KERN_ERR "imb_ioctl: copy_from_user pImbReq failed\n");
 			return -EFAULT;
 		}
 		if ((pImbReq->req.dataLength + MIN_IMB_REQ_BUF_SIZE)
-		    > smi.cbInBuffer)
+		    > smi->cbInBuffer)
 		{
 			return -EINVAL;
 		}
@@ -618,13 +625,11 @@ static int ipmi_imb_ioctl(struct inode  
 
 			ipmi_free_recv_msg(rsp);
 
-			if (copy_to_user(smi.lpvOutBuffer, pImbResp, length)) {
+			if (copy_to_user(smi->lpvOutBuffer, pImbResp, length)) {
 				return -EFAULT;
 			}
 
-			if (copy_to_user(smi.lpcbBytesReturned,
-					 &length,
-					 sizeof(length)))
+			if (copy_to_user(smi->lpcbBytesReturned, &length, sz))
 			{
 				return -EFAULT;
 			}
@@ -638,13 +643,13 @@ static int ipmi_imb_ioctl(struct inode  
 		ShutdownCmdBuffer shutdownCmd;
 
 		if (copy_from_user(&shutdownCmd,
-				   smi.lpvInBuffer,
+				   smi->lpvInBuffer,
 				   sizeof(ShutdownCmdBuffer)))
 		{
 			return -EFAULT;
 		}
 
-		if (smi.cbInBuffer < sizeof(ShutdownCmdBuffer))
+		if (smi->cbInBuffer < sizeof(ShutdownCmdBuffer))
 		{
 			return -EINVAL;
 		}
@@ -686,11 +691,10 @@ static int ipmi_imb_ioctl(struct inode  
 		//
 		dummy = 0xbabe;
 		memcpy(pImbResp->data,&dummy,length);
-		if (copy_to_user(smi.lpvOutBuffer, pImbResp, length))
+		if (copy_to_user(smi->lpvOutBuffer, pImbResp, length))
 			return -EFAULT;
 
-		if (copy_to_user(smi.lpcbBytesReturned, &length,
-				 sizeof(length)))
+		if (copy_to_user(smi->lpcbBytesReturned, &length, sz))
 			return -EFAULT;
 
 		rv = STATUS_SUCCESS;
@@ -736,6 +740,60 @@ static int ipmi_imb_ioctl(struct inode  
 	return rv;
 }
 
+#ifdef CONFIG_COMPAT
+#include <linux/ioctl32.h>
+#include <linux/compat.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14))
+static long ipmi_imb_ioctl32(struct file *filep, unsigned int cmd,
+                        unsigned long arg );
+static long ipmi_imb_ioctl32(struct file *filep, unsigned int cmd,
+                        unsigned long arg )
+#else
+static int  ipmi_imb_ioctl32(unsigned int fd, unsigned int cmd,
+                        unsigned long arg, struct file *filep);
+static int  ipmi_imb_ioctl32( unsigned int fd, unsigned int cmd,
+			unsigned long arg, struct file *filep)
+#endif
+{
+	int              rv = -EINVAL;
+	struct smi32     smi32;
+	struct smi       smi;
+
+	if (copy_from_user((caddr_t)&smi32, compat_ptr(arg), sizeof(smi32))) {
+		printk("imb_ioctl32(%x): copy_from_user error\n",cmd);
+		return -EFAULT;
+	}
+	smi.cbInBuffer  = smi32.cbInBuffer;
+	smi.cbOutBuffer = smi32.cbOutBuffer;
+	smi.lpvInBuffer  = compat_ptr(smi32.lpvInBuffer);
+	smi.lpvOutBuffer = compat_ptr(smi32.lpvOutBuffer);
+	smi.lpcbBytesReturned = compat_ptr(smi32.lpcbBytesReturned);
+
+#ifdef DEBUG
+        printk(KERN_INFO "imb_ioctl32(%x): cbIn=%ld cbOut=%ld\n",
+		cmd,smi.cbInBuffer,smi.cbOutBuffer);
+#endif
+	rv = ipmi_imb_ioctl_cmd(filep, cmd, &smi, 1);
+	return(rv);
+}
+#endif
+
+static int ipmi_imb_ioctl(struct inode  *inode,
+			  struct file   *file,
+			  unsigned int  cmd,
+			  unsigned long data)
+{
+	int              rv = -EINVAL;
+	struct smi       smi;
+	if (copy_from_user((caddr_t)&smi, (caddr_t)data, sizeof(smi))) {
+		printk("imb_ioctl(%x): copy_from_user error\n",cmd);
+		return -EFAULT;
+	}
+	rv = ipmi_imb_ioctl_cmd(file, cmd, &smi, 0);
+	return(rv);
+}
+
+
 static int ipmi_imb_mmap(struct file *file, struct vm_area_struct *vma)
 {
     off_t offset = vma->vm_pgoff << PAGE_SHIFT;
@@ -743,9 +801,19 @@ static int ipmi_imb_mmap(struct file *fi
     if (offset < 0)
 	    return -EINVAL;
 
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,3))
+    if (remap_page_range( vma->vm_start, offset,
+			vma->vm_end - vma->vm_start,
+			vma->vm_page_prot))
+#elif (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10))
+    if (remap_page_range(vma, vma->vm_start, offset,
+			vma->vm_end - vma->vm_start,
+			vma->vm_page_prot))
+#else
     if (remap_pfn_range(vma, vma->vm_start, offset,
 			vma->vm_end - vma->vm_start,
 			vma->vm_page_prot))
+#endif
     {
 	    return -EAGAIN;
     }
@@ -760,6 +828,11 @@ static int ipmi_imb_mmap(struct file *fi
 static struct file_operations ipmi_fops = {
 	owner:   THIS_MODULE,
 	ioctl:   ipmi_imb_ioctl,
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13))
+#ifdef CONFIG_COMPAT
+    	compat_ioctl:  ipmi_imb_ioctl32,
+#endif
+#endif
 	open:    ipmi_imb_open,
 	release: ipmi_imb_release,
 	mmap:    ipmi_imb_mmap
@@ -874,6 +947,30 @@ static int init_ipmi_imb(void)
 		ipmi_imb_major = rv;
 	}
 
+	devfs_mk_cdev(MKDEV(ipmi_imb_major, 0),
+		      S_IFCHR | S_IRUSR | S_IWUSR,
+		      DEVICE_NAME);
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14))
+#ifdef CONFIG_COMPAT
+    {
+	int err = 0;
+	err = register_ioctl32_conversion(IOCTL_IMB_SEND_MESSAGE, ipmi_imb_ioctl32);
+	err |= register_ioctl32_conversion(IOCTL_IMB_GET_ASYNC_MSG, ipmi_imb_ioctl3);
+	err |= register_ioctl32_conversion(IOCTL_IMB_MAP_MEMORY, ipmi_imb_ioctl32);
+	err |= register_ioctl32_conversion(IOCTL_IMB_UNMAP_MEMORY, ipmi_imb_ioctl32);
+	err |= register_ioctl32_conversion(IOCTL_IMB_SHUTDOWN_CODE, ipmi_imb_ioctl32);       
+	err |= register_ioctl32_conversion(IOCTL_IMB_REGISTER_ASYNC_OBJ,
+                                        ipmi_imb_ioctl32);
+	err |= register_ioctl32_conversion(IOCTL_IMB_DEREGISTER_ASYNC_OBJ,
+                                        ipmi_imb_ioctl32);
+	err |= register_ioctl32_conversion(IOCTL_IMB_CHECK_EVENT, ipmi_imb_ioctl32);
+	err |= register_ioctl32_conversion(IOCTL_IMB_POLL_ASYNC, ipmi_imb_ioctl32);
+	printk(KERN_INFO "register_ioctl32_conversion ret = %d\n",err);
+    }
+#endif
+#endif
+
 	init_timer(&ipmi_imb_timer);
 	ipmi_imb_timer.data = (long) ipmi_user;
 	ipmi_imb_timer.function = ipmi_imb_timeout;
@@ -901,6 +998,8 @@ static void free_recv_msg_list(struct li
 
 static void cleanup_ipmi_imb(void)
 {
+	devfs_remove(DEVICE_NAME);
+
 	/* Tell the timer to stop, then wait for it to stop.  This avoids
 	   problems with race conditions removing the timer here. */
 	stop_operation = 1;
@@ -916,6 +1015,22 @@ static void cleanup_ipmi_imb(void)
 	kfree(ipmi_user);
 	ipmi_user = NULL;
 
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14))
+#ifdef CONFIG_COMPAT
+    {
+       int err = 0;
+       err = unregister_ioctl32_conversion(IOCTL_IMB_SEND_MESSAGE);
+       err |= unregister_ioctl32_conversion(IOCTL_IMB_GET_ASYNC_MSG);
+       err |= unregister_ioctl32_conversion(IOCTL_IMB_MAP_MEMORY);
+       err |= unregister_ioctl32_conversion(IOCTL_IMB_UNMAP_MEMORY);
+       err |= unregister_ioctl32_conversion(IOCTL_IMB_SHUTDOWN_CODE);
+       err |= unregister_ioctl32_conversion(IOCTL_IMB_REGISTER_ASYNC_OBJ);
+       err |= unregister_ioctl32_conversion(IOCTL_IMB_DEREGISTER_ASYNC_OBJ);
+       err |= unregister_ioctl32_conversion(IOCTL_IMB_CHECK_EVENT);
+       err |= unregister_ioctl32_conversion(IOCTL_IMB_POLL_ASYNC);
+    }
+#endif
+#endif
 	unregister_chrdev(ipmi_imb_major, DEVICE_NAME);
 }
 module_exit(cleanup_ipmi_imb);
Index: linux-2.6.24/include/linux/ipmi_imb.h
===================================================================
--- linux-2.6.24.orig/include/linux/ipmi_imb.h
+++ linux-2.6.24/include/linux/ipmi_imb.h
@@ -34,6 +34,8 @@
 #ifndef __LINUX_IPMI_IMB_H
 #define __LINUX_IPMI_IMB_H
 
+#define UINT32  unsigned int   /* 32-bits, not 64-bit/long */
+
 typedef struct overlapped_s {
     unsigned long Internal;
     unsigned long InternalHigh;
@@ -54,6 +56,20 @@ struct smi {
     overlapped_t  *lpoOverlapped;     /* address of overlapped structure*/
 };
 
+/* smi32 is used for CONFIG_COMPAT */
+struct smi32 {
+    UINT32 smi_VersionNo;
+    UINT32 smi_Reserved1;
+    UINT32 smi_Reserved2;
+    UINT32 ntstatus;      /* address of NT status block*/
+    UINT32 lpvInBuffer;   /* address of buffer for input data*/
+    UINT32 cbInBuffer;    /* size of input buffer*/
+    UINT32 lpvOutBuffer;  /* address of output buffer*/
+    UINT32 cbOutBuffer;   /* size of output buffer*/
+    UINT32 lpcbBytesReturned; /* address of actual bytes of output*/
+    struct { UINT32 h[4]; } lpoOverlapped;  /* address of overlapped structure*/
+};
+
 
 #define MAX_IMB_PACKET_SIZE	33
 
@@ -67,10 +83,10 @@ typedef struct {
 } ImbRequest;
 
 typedef struct {
-	unsigned long flags;
+	UINT32 flags;
 #define	      		NO_RESPONSE_EXPECTED	0x01
 
-	unsigned long timeOut;
+	UINT32 timeOut;
 	ImbRequest    req;
 } ImbRequestBuffer;
 
@@ -91,16 +107,16 @@ typedef struct {
 #define MAX_IMB_RESPONSE_SIZE	MAX_IMB_PACKET_SIZE
 
 typedef struct {
-	unsigned long timeOut;
-	unsigned long lastSeq;
+	UINT32 timeOut;
+	UINT32 lastSeq;
 } ImbAsyncRequest;
 
 typedef struct {
-	unsigned long thisSeq;
+	UINT32 thisSeq;
 	unsigned char data[1];
 } ImbAsyncResponse;
 
-#define MIN_ASYNC_RESP_SIZE		sizeof(unsigned long)
+#define MIN_ASYNC_RESP_SIZE		sizeof(UINT32)
 #define MAX_ASYNC_RESP_SIZE		(MIN_ASYNC_RESP_SIZE + MAX_IMB_PACKET_SIZE)
 
 #define STATUS_SUCCESS                  (0x00000000U)
-------------------------------------------------------------------------
This SF.net email is sponsored by the 2008 JavaOne(SM) Conference 
Don't miss this year's exciting event. There's still time to save $100. 
Use priority code J8TL2D2. 
http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone
_______________________________________________
Openipmi-developer mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/openipmi-developer

Reply via email to