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