From owner-freebsd-bugs@FreeBSD.ORG Fri Feb 20 15:40:16 2004 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 1C31516A4CE for ; Fri, 20 Feb 2004 15:40:16 -0800 (PST) Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21]) by mx1.FreeBSD.org (Postfix) with ESMTP id 105C243D46 for ; Fri, 20 Feb 2004 15:40:16 -0800 (PST) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) i1KNeFbv030128 for ; Fri, 20 Feb 2004 15:40:15 -0800 (PST) (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.12.10/8.12.10/Submit) id i1KNeFmM030127; Fri, 20 Feb 2004 15:40:15 -0800 (PST) (envelope-from gnats) Resent-Date: Fri, 20 Feb 2004 15:40:15 -0800 (PST) Resent-Message-Id: <200402202340.i1KNeFmM030127@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Mikhail Teterin Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 1966316A4CE; Fri, 20 Feb 2004 15:34:12 -0800 (PST) Received: from corbulon.video-collage.com (corbulon.video-collage.com [64.35.99.179]) by mx1.FreeBSD.org (Postfix) with ESMTP id 9BCED43D41; Fri, 20 Feb 2004 15:34:11 -0800 (PST) (envelope-from mteterin@250-217.customer.cloud9.net) Received: from 250-217.customer.cloud9.net (195-11.customer.cloud9.net [168.100.195.11])i1KNY5Wf089162 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 20 Feb 2004 18:34:08 -0500 (EST) (envelope-from mteterin@250-217.customer.cloud9.net) Received: from 250-217.customer.cloud9.net (mteterin@localhost [127.0.0.1]) i1KNXow4087376 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Fri, 20 Feb 2004 18:33:51 -0500 (EST) (envelope-from mteterin@250-217.customer.cloud9.net) Received: (from mteterin@localhost)i1KNXoVq087375; Fri, 20 Feb 2004 18:33:50 -0500 (EST) (envelope-from mteterin) Message-Id: <200402202333.i1KNXoVq087375@250-217.customer.cloud9.net> Date: Fri, 20 Feb 2004 18:33:50 -0500 (EST) From: Mikhail Teterin To: FreeBSD-gnats-submit@FreeBSD.org X-Send-Pr-Version: 3.113 cc: msmith@FreeBSD.org Subject: kern/63155: [patch] amr(4) ioctl fails for 32-bit binaries on 64-bit X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list Reply-To: Mikhail Teterin List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 20 Feb 2004 23:40:16 -0000 >Number: 63155 >Category: kern >Synopsis: [patch] amr(4) ioctl fails for 32-bit binaries on 64-bit >Confidential: no >Severity: serious >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Fri Feb 20 15:40:11 PST 2004 >Closed-Date: >Last-Modified: >Originator: Mikhail Teterin >Release: FreeBSD 5.2-RELEASE i386 >Organization: Virtual Estates, Inc. >Environment: System: 5.2-CURRENT >Description: The only known program, that uses the amr(4)'s AMR_IO_COMMAND ioctl seems to be the LSI's binary called MEGAMGR. It allows to do all the manipulations available from the controller's BIOS in user space. The program is a staticly linked 32-bit binary, which lets it run on an amd64 machine (and, presumably, on ia64). However, due to the difference in the size of ``struct amr_user_ioctl'', the actual ioctl number of AMR_IO_COMMAND is different, so the utility exits with "No adapters found". The patch below creates a compatibility structure amr_user_ioctl32, and the corresponding ioctl number AMR_IO_COMMAND32. It tells the amr_ioctl() how to handle this new ioctl. I tested this patch with MEGAMGR and was able to do all modifications to the array I wanted. But I did not try the SCSI pass-through, so... The problems with the patch, that remain are: . detecting the kernel's target platform -- whether the separate AMR_IO_COMMAND32 is needed at all -- the #if _MACHINE_ARCH == amd64 || _MACHINE_ARCH == ia64 is not enough, for some reason; . the whole sys/dev/amr seems to use 4 spaces in deviation from a single tab specified by style(9) -- in accordance with the man page I tried to preserve the existing style, but may have missed a line or two. Both problems should be easy to fix by anyone -- please, help. >How-To-Repeat: >Fix: Index: amr.c =================================================================== RCS file: /home/ncvs/src/sys/dev/amr/amr.c,v retrieving revision 1.50 diff -U2 -r1.50 amr.c --- amr.c 8 Feb 2004 16:07:22 -0000 1.50 +++ amr.c 20 Feb 2004 23:29:36 -0000 @@ -397,117 +397,150 @@ { struct amr_softc *sc = (struct amr_softc *)dev->si_drv1; - int *arg = (int *)addr; - struct amr_user_ioctl *au = (struct amr_user_ioctl *)addr; + union { + void *_p; + struct amr_user_ioctl *au; +#ifdef AMR_IO_COMMAND32 + struct amr_user_ioctl32 *au32; +#endif + int *result; + } arg; struct amr_command *ac; struct amr_mailbox_ioctl *mbi; struct amr_passthrough *ap; - void *dp; + void *dp, *au_buffer; + unsigned long au_length; + unsigned char *au_cmd; + int *au_statusp, au_direction; int error; debug_called(1); - error = 0; - dp = NULL; - ap = NULL; - ac = NULL; + arg._p = (void *)addr; + switch(cmd) { case AMR_IO_VERSION: debug(1, "AMR_IO_VERSION"); - *arg = AMR_IO_VERSION_NUMBER; + *arg.result = AMR_IO_VERSION_NUMBER; + return(0); + +#ifdef AMR_IO_COMMAND32 + /* + * Accept ioctl-s from 32-bit binaries on non-32-bit + * platforms, such as AMD. LSI's MEGAMGR utility is + * the only example known today... -mi + */ + case AMR_IO_COMMAND32: + debug(1, "AMR_IO_COMMAND32 0x%x", arg.au32->au_cmd[0]); + au_cmd = arg.au32->au_cmd; + au_buffer = (void *)(u_int64_t)arg.au32->au_buffer; + au_length = arg.au32->au_length; + au_direction = arg.au32->au_direction; + au_statusp = &arg.au32->au_status; break; +#endif case AMR_IO_COMMAND: - debug(1, "AMR_IO_COMMAND 0x%x", au->au_cmd[0]); - /* handle inbound data buffer */ - if (au->au_length != 0) { - if ((dp = malloc(au->au_length, M_DEVBUF, M_WAITOK)) == NULL) { - error = ENOMEM; - break; - } - if ((error = copyin(au->au_buffer, dp, au->au_length)) != 0) - break; - debug(2, "copyin %ld bytes from %p -> %p", au->au_length, au->au_buffer, dp); - } + debug(1, "AMR_IO_COMMAND 0x%x", arg.au->au_cmd[0]); + au_cmd = arg.au->au_cmd; + au_buffer = (void *)arg.au->au_buffer; + au_length = arg.au->au_length; + au_direction = arg.au->au_direction; + au_statusp = &arg.au->au_status; + break; - if ((ac = amr_alloccmd(sc)) == NULL) { + default: + debug(1, "unknown ioctl 0x%lx", cmd); + return(ENOIOCTL); + } + + error = 0; + dp = NULL; + ap = NULL; + ac = NULL; + + /* handle inbound data buffer */ + if (au_length != 0) { + if ((dp = malloc(au_length, M_DEVBUF, M_WAITOK)) == NULL) + return(ENOMEM); + + if ((error = copyin(au_buffer, dp, au_length)) != 0) + goto out; + debug(2, "copyin %ld bytes from %p -> %p", au_length, au_buffer, dp); + } + + if ((ac = amr_alloccmd(sc)) == NULL) { + error = ENOMEM; + goto out; + } + + /* handle SCSI passthrough command */ + if (au_cmd[0] == AMR_CMD_PASS) { + if ((ap = malloc(sizeof(*ap), M_DEVBUF, M_WAITOK | M_ZERO)) == NULL) { error = ENOMEM; - break; + goto out; } - /* handle SCSI passthrough command */ - if (au->au_cmd[0] == AMR_CMD_PASS) { - if ((ap = malloc(sizeof(*ap), M_DEVBUF, M_WAITOK | M_ZERO)) == NULL) { - error = ENOMEM; - break; - } - - /* copy cdb */ - ap->ap_cdb_length = au->au_cmd[2]; - bcopy(&au->au_cmd[3], &ap->ap_cdb[0], ap->ap_cdb_length); - - /* build passthrough */ - ap->ap_timeout = au->au_cmd[ap->ap_cdb_length + 3] & 0x07; - ap->ap_ars = (au->au_cmd[ap->ap_cdb_length + 3] & 0x08) ? 1 : 0; - ap->ap_islogical = (au->au_cmd[ap->ap_cdb_length + 3] & 0x80) ? 1 : 0; - ap->ap_logical_drive_no = au->au_cmd[ap->ap_cdb_length + 4]; - ap->ap_channel = au->au_cmd[ap->ap_cdb_length + 5]; - ap->ap_scsi_id = au->au_cmd[ap->ap_cdb_length + 6]; - ap->ap_request_sense_length = 14; - ap->ap_data_transfer_length = au->au_length; - /* XXX what about the request-sense area? does the caller want it? */ - - /* build command */ - ac->ac_data = ap; - ac->ac_length = sizeof(*ap); + /* copy cdb */ + ap->ap_cdb_length = au_cmd[2]; + bcopy(au_cmd + 3, ap->ap_cdb, ap->ap_cdb_length); + + /* build passthrough */ + ap->ap_timeout = au_cmd[ap->ap_cdb_length + 3] & 0x07; + ap->ap_ars = (au_cmd[ap->ap_cdb_length + 3] & 0x08) ? 1 : 0; + ap->ap_islogical = (au_cmd[ap->ap_cdb_length + 3] & 0x80) ? 1 : 0; + ap->ap_logical_drive_no = au_cmd[ap->ap_cdb_length + 4]; + ap->ap_channel = au_cmd[ap->ap_cdb_length + 5]; + ap->ap_scsi_id = au_cmd[ap->ap_cdb_length + 6]; + ap->ap_request_sense_length = 14; + ap->ap_data_transfer_length = au_length; + /* XXX what about the request-sense area? does the caller want it? */ + + /* build command */ + ac->ac_data = ap; + ac->ac_length = sizeof(*ap); + ac->ac_flags |= AMR_CMD_DATAOUT; + ac->ac_ccb_data = dp; + ac->ac_ccb_length = au_length; + if (au_direction & AMR_IO_READ) + ac->ac_flags |= AMR_CMD_CCB_DATAIN; + if (au_direction & AMR_IO_WRITE) + ac->ac_flags |= AMR_CMD_CCB_DATAOUT; + + ac->ac_mailbox.mb_command = AMR_CMD_PASS; + + } else { + /* direct command to controller */ + mbi = (struct amr_mailbox_ioctl *)&ac->ac_mailbox; + + /* copy pertinent mailbox items */ + mbi->mb_command = au_cmd[0]; + mbi->mb_channel = au_cmd[1]; + mbi->mb_param = au_cmd[2]; + mbi->mb_pad[0] = au_cmd[3]; + mbi->mb_drive = au_cmd[4]; + + /* build the command */ + ac->ac_data = dp; + ac->ac_length = au_length; + if (au_direction & AMR_IO_READ) + ac->ac_flags |= AMR_CMD_DATAIN; + if (au_direction & AMR_IO_WRITE) ac->ac_flags |= AMR_CMD_DATAOUT; - ac->ac_ccb_data = dp; - ac->ac_ccb_length = au->au_length; - if (au->au_direction & AMR_IO_READ) - ac->ac_flags |= AMR_CMD_CCB_DATAIN; - if (au->au_direction & AMR_IO_WRITE) - ac->ac_flags |= AMR_CMD_CCB_DATAOUT; - - ac->ac_mailbox.mb_command = AMR_CMD_PASS; - - } else { - /* direct command to controller */ - mbi = (struct amr_mailbox_ioctl *)&ac->ac_mailbox; - - /* copy pertinent mailbox items */ - mbi->mb_command = au->au_cmd[0]; - mbi->mb_channel = au->au_cmd[1]; - mbi->mb_param = au->au_cmd[2]; - mbi->mb_pad[0] = au->au_cmd[3]; - mbi->mb_drive = au->au_cmd[4]; - - /* build the command */ - ac->ac_data = dp; - ac->ac_length = au->au_length; - if (au->au_direction & AMR_IO_READ) - ac->ac_flags |= AMR_CMD_DATAIN; - if (au->au_direction & AMR_IO_WRITE) - ac->ac_flags |= AMR_CMD_DATAOUT; - } - - /* run the command */ - if ((error = amr_wait_command(ac)) != 0) - break; - - /* copy out data and set status */ - if (au->au_length != 0) - error = copyout(dp, au->au_buffer, au->au_length); - debug(2, "copyout %ld bytes from %p -> %p", au->au_length, dp, au->au_buffer); - if (dp != NULL) - debug(2, "%16d", (int)dp); - au->au_status = ac->ac_status; - break; - - default: - debug(1, "unknown ioctl 0x%lx", cmd); - error = ENOIOCTL; - break; } + /* run the command */ + if ((error = amr_wait_command(ac)) != 0) + goto out; + + /* copy out data and set status */ + if (au_length != 0) + error = copyout(dp, au_buffer, au_length); + debug(2, "copyout %ld bytes from %p -> %p", au_length, dp, au_buffer); + if (dp != NULL) + debug(2, "%16d", (int)dp); + *au_statusp = ac->ac_status; + +out: if (dp != NULL) free(dp, M_DEVBUF); Index: amrio.h =================================================================== RCS file: /home/ncvs/src/sys/dev/amr/amrio.h,v retrieving revision 1.5 diff -U2 -r1.5 amrio.h --- amrio.h 30 Oct 2002 22:00:11 -0000 1.5 +++ amrio.h 20 Feb 2004 23:29:37 -0000 @@ -61,4 +61,5 @@ #include +#include /* @@ -108,2 +109,14 @@ #define AMR_IO_COMMAND _IOWR('A', 0x201, struct amr_user_ioctl) +#if _MACHINE_ARCH == amd64 || _MACHINE_ARCH == ia64 + +struct amr_user_ioctl32 { + unsigned char au_cmd[32]; /* command text from userspace */ + u_int32_t au_buffer; /* 32-bit pointer to uspace buf */ + u_int32_t au_length; /* length of the uspace buffer */ + int32_t au_direction; /* data transfer direction */ + int32_t au_status; /* command status returned by adapter */ +}; + +# define AMR_IO_COMMAND32 _IOWR('A', 0x201, struct amr_user_ioctl32) +#endif >Release-Note: >Audit-Trail: >Unformatted: