aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
authorAndrew Morton <akpm@osdl.org>2005-06-24 01:01:45 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-06-24 03:05:24 -0400
commit6a94f9209762a6eb286f668e1346ad87985cc765 (patch)
tree1dbff088e8340cde187fc581a549bacde26d798f /drivers/char
parent77cf3973f22c7e7158f5e2c3c3d6809125b77e4b (diff)
[PATCH] ipmi: add 32-bit ioctl translations for 64-bit platforms
) From: Corey Minyard <minyard@acm.org> This contains the patch for supporting 32-bit compatible ioctls on x86_64 systems. The current x86_64 driver will not work with 32-bit applications. Signed-off-by: Jordan Hargave <jordan_hargrave@dell.com> Signed-off-by: Corey Minyard <minyard@acm.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/ipmi/ipmi_devintf.c196
1 files changed, 196 insertions, 0 deletions
diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c
index 88d1ad656e99..e0a53570fea1 100644
--- a/drivers/char/ipmi/ipmi_devintf.c
+++ b/drivers/char/ipmi/ipmi_devintf.c
@@ -45,6 +45,7 @@
45#include <asm/semaphore.h> 45#include <asm/semaphore.h>
46#include <linux/init.h> 46#include <linux/init.h>
47#include <linux/device.h> 47#include <linux/device.h>
48#include <linux/compat.h>
48 49
49#define IPMI_DEVINTF_VERSION "v33" 50#define IPMI_DEVINTF_VERSION "v33"
50 51
@@ -500,10 +501,205 @@ static int ipmi_ioctl(struct inode *inode,
500 return rv; 501 return rv;
501} 502}
502 503
504#ifdef CONFIG_COMPAT
505
506/*
507 * The following code contains code for supporting 32-bit compatible
508 * ioctls on 64-bit kernels. This allows running 32-bit apps on the
509 * 64-bit kernel
510 */
511#define COMPAT_IPMICTL_SEND_COMMAND \
512 _IOR(IPMI_IOC_MAGIC, 13, struct compat_ipmi_req)
513#define COMPAT_IPMICTL_SEND_COMMAND_SETTIME \
514 _IOR(IPMI_IOC_MAGIC, 21, struct compat_ipmi_req_settime)
515#define COMPAT_IPMICTL_RECEIVE_MSG \
516 _IOWR(IPMI_IOC_MAGIC, 12, struct compat_ipmi_recv)
517#define COMPAT_IPMICTL_RECEIVE_MSG_TRUNC \
518 _IOWR(IPMI_IOC_MAGIC, 11, struct compat_ipmi_recv)
519
520struct compat_ipmi_msg {
521 u8 netfn;
522 u8 cmd;
523 u16 data_len;
524 compat_uptr_t data;
525};
526
527struct compat_ipmi_req {
528 compat_uptr_t addr;
529 compat_uint_t addr_len;
530 compat_long_t msgid;
531 struct compat_ipmi_msg msg;
532};
533
534struct compat_ipmi_recv {
535 compat_int_t recv_type;
536 compat_uptr_t addr;
537 compat_uint_t addr_len;
538 compat_long_t msgid;
539 struct compat_ipmi_msg msg;
540};
541
542struct compat_ipmi_req_settime {
543 struct compat_ipmi_req req;
544 compat_int_t retries;
545 compat_uint_t retry_time_ms;
546};
547
548/*
549 * Define some helper functions for copying IPMI data
550 */
551static long get_compat_ipmi_msg(struct ipmi_msg *p64,
552 struct compat_ipmi_msg __user *p32)
553{
554 compat_uptr_t tmp;
555
556 if (!access_ok(VERIFY_READ, p32, sizeof(*p32)) ||
557 __get_user(p64->netfn, &p32->netfn) ||
558 __get_user(p64->cmd, &p32->cmd) ||
559 __get_user(p64->data_len, &p32->data_len) ||
560 __get_user(tmp, &p32->data))
561 return -EFAULT;
562 p64->data = compat_ptr(tmp);
563 return 0;
564}
565
566static long put_compat_ipmi_msg(struct ipmi_msg *p64,
567 struct compat_ipmi_msg __user *p32)
568{
569 if (!access_ok(VERIFY_WRITE, p32, sizeof(*p32)) ||
570 __put_user(p64->netfn, &p32->netfn) ||
571 __put_user(p64->cmd, &p32->cmd) ||
572 __put_user(p64->data_len, &p32->data_len))
573 return -EFAULT;
574 return 0;
575}
576
577static long get_compat_ipmi_req(struct ipmi_req *p64,
578 struct compat_ipmi_req __user *p32)
579{
580
581 compat_uptr_t tmp;
582
583 if (!access_ok(VERIFY_READ, p32, sizeof(*p32)) ||
584 __get_user(tmp, &p32->addr) ||
585 __get_user(p64->addr_len, &p32->addr_len) ||
586 __get_user(p64->msgid, &p32->msgid) ||
587 get_compat_ipmi_msg(&p64->msg, &p32->msg))
588 return -EFAULT;
589 p64->addr = compat_ptr(tmp);
590 return 0;
591}
592
593static long get_compat_ipmi_req_settime(struct ipmi_req_settime *p64,
594 struct compat_ipmi_req_settime __user *p32)
595{
596 if (!access_ok(VERIFY_READ, p32, sizeof(*p32)) ||
597 get_compat_ipmi_req(&p64->req, &p32->req) ||
598 __get_user(p64->retries, &p32->retries) ||
599 __get_user(p64->retry_time_ms, &p32->retry_time_ms))
600 return -EFAULT;
601 return 0;
602}
603
604static long get_compat_ipmi_recv(struct ipmi_recv *p64,
605 struct compat_ipmi_recv __user *p32)
606{
607 compat_uptr_t tmp;
608
609 if (!access_ok(VERIFY_READ, p32, sizeof(*p32)) ||
610 __get_user(p64->recv_type, &p32->recv_type) ||
611 __get_user(tmp, &p32->addr) ||
612 __get_user(p64->addr_len, &p32->addr_len) ||
613 __get_user(p64->msgid, &p32->msgid) ||
614 get_compat_ipmi_msg(&p64->msg, &p32->msg))
615 return -EFAULT;
616 p64->addr = compat_ptr(tmp);
617 return 0;
618}
619
620static long put_compat_ipmi_recv(struct ipmi_recv *p64,
621 struct compat_ipmi_recv __user *p32)
622{
623 if (!access_ok(VERIFY_WRITE, p32, sizeof(*p32)) ||
624 __put_user(p64->recv_type, &p32->recv_type) ||
625 __put_user(p64->addr_len, &p32->addr_len) ||
626 __put_user(p64->msgid, &p32->msgid) ||
627 put_compat_ipmi_msg(&p64->msg, &p32->msg))
628 return -EFAULT;
629 return 0;
630}
631
632/*
633 * Handle compatibility ioctls
634 */
635static long compat_ipmi_ioctl(struct file *filep, unsigned int cmd,
636 unsigned long arg)
637{
638 int rc;
639 struct ipmi_file_private *priv = filep->private_data;
640
641 switch(cmd) {
642 case COMPAT_IPMICTL_SEND_COMMAND:
643 {
644 struct ipmi_req rp;
645
646 if (get_compat_ipmi_req(&rp, compat_ptr(arg)))
647 return -EFAULT;
648
649 return handle_send_req(priv->user, &rp,
650 priv->default_retries,
651 priv->default_retry_time_ms);
652 }
653 case COMPAT_IPMICTL_SEND_COMMAND_SETTIME:
654 {
655 struct ipmi_req_settime sp;
656
657 if (get_compat_ipmi_req_settime(&sp, compat_ptr(arg)))
658 return -EFAULT;
659
660 return handle_send_req(priv->user, &sp.req,
661 sp.retries, sp.retry_time_ms);
662 }
663 case COMPAT_IPMICTL_RECEIVE_MSG:
664 case COMPAT_IPMICTL_RECEIVE_MSG_TRUNC:
665 {
666 struct ipmi_recv *precv64, recv64;
667
668 if (get_compat_ipmi_recv(&recv64, compat_ptr(arg)))
669 return -EFAULT;
670
671 precv64 = compat_alloc_user_space(sizeof(recv64));
672 if (copy_to_user(precv64, &recv64, sizeof(recv64)))
673 return -EFAULT;
674
675 rc = ipmi_ioctl(filep->f_dentry->d_inode, filep,
676 ((cmd == COMPAT_IPMICTL_RECEIVE_MSG)
677 ? IPMICTL_RECEIVE_MSG
678 : IPMICTL_RECEIVE_MSG_TRUNC),
679 (long) precv64);
680 if (rc != 0)
681 return rc;
682
683 if (copy_from_user(&recv64, precv64, sizeof(recv64)))
684 return -EFAULT;
685
686 if (put_compat_ipmi_recv(&recv64, compat_ptr(arg)))
687 return -EFAULT;
688
689 return rc;
690 }
691 default:
692 return ipmi_ioctl(filep->f_dentry->d_inode, filep, cmd, arg);
693 }
694}
695#endif
503 696
504static struct file_operations ipmi_fops = { 697static struct file_operations ipmi_fops = {
505 .owner = THIS_MODULE, 698 .owner = THIS_MODULE,
506 .ioctl = ipmi_ioctl, 699 .ioctl = ipmi_ioctl,
700#ifdef CONFIG_COMPAT
701 .compat_ioctl = compat_ipmi_ioctl,
702#endif
507 .open = ipmi_open, 703 .open = ipmi_open,
508 .release = ipmi_release, 704 .release = ipmi_release,
509 .fasync = ipmi_fasync, 705 .fasync = ipmi_fasync,