/dev/port BUG and possible workaround
Hello!
It seems that I've found out bug in subj
(sorry if this subj was already discussed here)
looking at sources of drivers/char/mem.c I found out:
static ssize_t read_port(struct file * file, char * buf,
size_t count, loff_t *ppos)
{
unsigned long i = *ppos;
[snip]
while (count-- > 0 && i < 65536) {
if (__put_user(inb(i),tmp) < 0)
return -EFAULT; [snip]
}
static ssize_t write_port(struct file * file, const char * buf,
size_t count, loff_t *ppos)
{
unsigned long i = *ppos;
[snip]
while (count-- > 0 && i < 65536) {
char c;
if (__get_user(c, tmp))
return -EFAULT;
outb(c,i);[snip]
}
Well, when I'm trying to use this device in the way:
lseek(port_fd,port_idx,SEEK_SET); write(port_fd,&val32,4);
I get perfectly broken results due outl() != outb()*4 Please look at logs:
1. Correct log with using of inport/outport:outb(CF8,0)outb(CFA,0)
FF=inb(CF8)
FF=inb(CFA)
80FFFFFC=inl(CF8)outl(CF8,80000000)
80000000=inl(CF8)outl(CF8,80FFFFFC)outl(CF8,80000000)
3051106=inl(CFC)outl(CF8,80000004)
22100006=inl(CFC)outl(CF8,80000008)
6000003=inl(CFC)outl(CF8,8000000C)
800=inl(CFC)
2. Wrong log with using of /dev/port:outb(CF8,0)outb(CFA,0)
FF=inb(CF8)
FF=inb(CFA)
FFFFFFFF=inl(CF8)outl(CF8,80000000)
FFFFFFFF=inl(CF8)outl(CF8,FFFFFFFF)
As possible workaround it would be better to examine size of buffer and use corresponded insn within of these functions:
switch(size)
{
case 4: outl
case 2: outw
default: outb
}
But it seems that nobody uses this device. Then what is goal of implementing of this device?
Best regards! Nick
Uz.ytkownik Nick Kurshev napisa?:
...
Quoted 2 lines
800=inl(CFC)
2. Wrong log with using of/dev/port:
...
Quoted 2 lines
But it seems that nobody uses this device. Then what is goal of implementing of this device?
Basically the goal is that contrary to some silly /proc stuff which is "en vouge" nowadays you have the ability to controll port access by using normal user permission control semantics of unix file access permissions, by giving /dev/port a proper group and so on. This is legacy crap of course, since the above goal can be reached by using a apache-suexec alike wrapper as well... even with more fine grained resolution of access controll.
Hello, Martin!
Quoted 9 lines · On Wed, 22 May 2002 09:52:35 +0200 you wrote:
Uz.ytkownik Nick Kurshev napisa?:
...
Quoted 2 lines
800=inl(CFC)
2. Wrong log with using of/dev/port:...
Quoted 8 lines
Quoted 2 lines
But it seems that nobody uses this device. Then what is goal of implementing of this device?
Basically the goal is that contrary to some silly /proc stuff which is "en vouge" nowadays you have the ability to controll port access by using normal user permission control semantics of unix file access permissions, by giving
/dev/porta proper group and so on. This is legacy crap of course, since
But this device is unworking in general. It simply unusable for programs which require 4-byte operations with ports. As I wrote: outl() != 4*outb() same as inl() != 4*inb()
Quoted 3 lines
the above goal can be reached by using a apache-suexec alike wrapper as well... even with more fine grained resolution of access controll.
Maybe after fixing these flaws it will be usable but not for now.
Best regards! Nick
Quoted 12 lines · Martin Dalecki
Uz.ytkownik Nick Kurshev napisa?:
...
Quoted 2 lines
800=inl(CFC)
2. Wrong log with using of/dev/port:...
Quoted 2 lines
But it seems that nobody uses this device. Then what is goal of implementing of this device?
Quoted 7 lines
Basically the goal is that contrary to some silly /proc stuff which is "en vouge" nowadays you have the ability to controll port access by using normal user permission control semantics of unix file access permissions, by giving
/dev/porta proper group and so on. This is legacy crap of course, since the above goal can be reached by using a apache-suexec alike wrapper as well... even with more fine grained resolution of access controll.
It also allows you to write a watchdog driver in shell :-)
#!/bin/sh
# [email protected]
# This supports both the Ibase MB700 and Advantech PCM9576
usage() {
echo "Usage: basename $0 [pat] [playdead]"
exit 1
}
if [ $# != 1 ]; then usage; fi;
if [ $1 != "pat" ]; then
if [ $1 != "playdead" ]; then
usage
fifi
HW_VERSION=cat /var/run/HW_VERSION
if [ "$HW_VERSION" == "IBASE MB700" ];
ENABLE_PORT=`printf %d 0x443`
DISABLE_PORT=`printf %d 0x441`
if [ $1 == "pat" ]; then
TIMEOUT='\x5' #20 seconds (0=30s, 1=28s, ..., F=0s)
printf "$TIMEOUT" | dd bs=1 seek=$ENABLE_PORT of=/dev/port
else
#write any value to port to disable
printf "\001" | dd bs=1 seek=$DISABLE_PORT of=/dev/port
fielif [ "$HW_VERSION" == "Advantech PCM9576" ]; then
DISENABLE_PORT=printf %d 0x443
if [ $1 == "pat" ]; then
TIMEOUT='\x14' #20 seconds (1=1s, 2=2s, ..., 3E=62s) printf "$TIMEOUT" | dd bs=1 seek=$DISENABLE_PORT of=/dev/port
else
#read from port to disable
dd bs=1 count=1 skip=$DISENABLE_PORT if=/dev/port of=/dev/null
fi
fi