【GitHub开源项目】https://github.com/sig-ishihara/linux_pysical_address_rw_cmd
Table of Contents
IO端口的in/out操作
内存的读写操作
PCI的读写操作
IO端口的in/out操作
/** io.c* ver.0.1: Dec 18, 2011 S.Ishihara*/
#include <stdio.h>
#include <unistd.h>
#include <sys/io.h>int main(int argc, char *argv[])
{int opt;extern char *optarg;extern int optind, opterr;int width = 1; /* default byte access */unsigned short ioaddr;unsigned int wdata;while ((opt = getopt(argc, argv, "w:")) != -1) {if (opt == 'w') {width = atoi(optarg);} else {goto error;}}argc -= optind;argv += optind;//iopl - change I/O privilege level//该调用用于修改当前进程的操作端口的权限。//level: 端口的权限级别。为3时可以读写端口。默认权能级别为0,用户空间不可读写。//EINVAL:level值大于3//ENOSYS:未实现该调用//EPERM:调用进程权能不足。iopl(3);//在差别 I/O 空间和内存空间的进程的 I/O 空间写入数据。//outb() I/O 上写入 8 位数据 ( 1 字节 )。//outw() I/O 上写入 16 位数据 ( 2 字节 );//outl () I/O 上写入 32 位数据 ( 4 字节)。if (argc == 1) {/* Read I/O */ioaddr = strtoul(argv[0], NULL, 16);printf("ioaddr = %d, width = %d\n", ioaddr, width);if (width == 1) {printf("0x%04x: 0x%02x\n", ioaddr, inb(ioaddr));} else if (width == 2) {printf("0x%04x: 0x%04x\n", ioaddr, inw(ioaddr));} else if (width == 4) {printf("0x%04x: 0x%08x\n", ioaddr, inl(ioaddr));} else {goto error;}} else if (argc == 2) {/* Write I/O */ioaddr = strtoul(argv[0], NULL, 16);wdata = strtoul(argv[1], NULL, 16);if (width == 1) {outb(wdata, ioaddr);} else if(width == 2) {outw(wdata, ioaddr);} else if(width == 4) {outl(wdata, ioaddr);} else {goto error;}} else {goto error;}return 0;error:printf("Usage: io [-w WIDTH] ADDRESS [DATA]\n""I/O read or write.\n"" -w number of byte width. permit 1(default), 2, 4\n""\n""This command executable only root user.\n""I/O address possible range 16bit.\n""\n""Examples:\n"" io 3f8 Read I/O from address 0x3f8.\n"" io 3f8 0x31 Write I/O address 0x3f8 to 0x31.\n"" io -w4 cf8 80000000 Write I/O address 0xcf8 to 0x80000000 double word.\n""\n");return 1;
}
内存的读写操作
/** mem.c* ver.0.1: Dec 26, 2011 S.Ishihara*/#include <stdio.h>
#include <unistd.h>
#include <sys/io.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>#define DEV_PATH "/dev/mem"int
main(int argc, char *argv[])
{int opt;extern char *optarg;extern int optind, opterr;int width = 1; /* default byte access */unsigned int memaddr, wdata;unsigned int pgoffset, pgaddr;unsigned int pagesize = sysconf(_SC_PAGESIZE);unsigned char *p;int fd;while ((opt = getopt(argc, argv, "w:")) != -1) {if (opt == 'w') {width = atoi(optarg);} else {goto error;}}argc -= optind;argv += optind;fd = open(DEV_PATH, O_RDWR);if (fd <= 0) {fprintf(stderr, "open error: %s\n", DEV_PATH);return 1;}if (argc == 1) {/* Read Mem */memaddr = strtoul(argv[0], NULL, 16);pgoffset = memaddr & (pagesize -1);pgaddr = memaddr & ~(pagesize -1);p = mmap(NULL, pagesize, PROT_READ, MAP_SHARED, fd, pgaddr);if (p < 0) {fprintf(stderr, "mmap error\n");return 1;}if (width == 1) {printf("0x%08x: 0x%02x\n", memaddr, *(p + pgoffset));} else if (width == 2) {printf("0x%08x: 0x%04x\n", memaddr, *((unsigned short *)(p + pgoffset)));} else if (width == 4) {printf("0x%08x: 0x%08x\n", memaddr, *((unsigned int *)(p + pgoffset)));} else {goto error;}} else if (argc == 2) {/* Write Mem */memaddr = strtoul(argv[0], NULL, 16);pgoffset = memaddr & (pagesize -1);pgaddr = memaddr & ~(pagesize -1);p = mmap(NULL, pagesize, PROT_WRITE, MAP_SHARED, fd, pgaddr);if (p < 0) {fprintf(stderr, "mmap error\n");return 1;}wdata = strtoul(argv[1], NULL, 16);if (width == 1) {*(p + pgoffset) = (unsigned char)wdata;} else if(width == 2) {*((unsigned short *)(p + pgoffset)) = (unsigned short)wdata;} else if(width == 4) {*((unsigned int *)(p + pgoffset)) = (unsigned int)wdata;} else {goto error;}} else {goto error;}munmap(p, pagesize);close(fd);return 0;error:printf("Usage: Mem [-w WIDTH] ADDRESS [DATA]\n""Mem read or write.\n"" -w number of byte width. permit 1(default), 2, 4\n""\n""This command executable only root user.\n""Mem address possible range 32bit.\n""\n""Examples:\n"" Mem a0000 Read memory from address 0xa0000.\n"" Mem a0000 31 Write memory address 0xa0000 to 0x31.\n"" Mem -w4 20000 5a5a5a5a Write memory address 0x20000 to 0x5a5a5a5a.\n""\n");return 1;
}
PCI的读写操作
/** pci.c* ver.0.1: Dec 18, 2011 S.Ishihara*/#include <stdio.h>
#include <unistd.h>
#include <sys/io.h>#define PCI_INDEX 0xcf8
#define PCI_DATA 0xcfcunsigned char
pciRead8(unsigned char bus, unsigned char dev, unsigned char fnc, unsigned char reg)
{outl((1 << 31) + (bus << 16) + ((dev & 0x1f) << 11) +\((fnc & 0x07) << 8) + (reg & ~(0x03)), PCI_INDEX);return inb(PCI_DATA + (reg & 0x03));
}unsigned short
pciRead16(unsigned char bus, unsigned char dev, unsigned char fnc, unsigned char reg)
{outl((1 << 31) + (bus << 16) + ((dev & 0x1f) << 11) +\((fnc & 0x07) << 8) + (reg & ~(0x03)), PCI_INDEX);return inw(PCI_DATA + (reg & 0x02));
}unsigned int
pciRead32(unsigned char bus, unsigned char dev, unsigned char fnc, unsigned char reg)
{outl((1 << 31) + (bus << 16) + ((dev & 0x1f) << 11) +\((fnc & 0x07) << 8) + (reg & ~(0x03)), PCI_INDEX);return inl(PCI_DATA);
}void
pciWrite8(unsigned char bus, unsigned char dev, unsigned char fnc, unsigned char reg, unsigned char value)
{outl((1 << 31) + (bus << 16) + ((dev & 0x1f) << 11) +\((fnc & 0x07) << 8) + (reg & ~(0x03)), PCI_INDEX);outb(value, PCI_DATA + (reg & 0x03));
}void
pciWrite16(unsigned char bus, unsigned char dev, unsigned char fnc, unsigned char reg, unsigned short value)
{outl((1 << 31) + (bus << 16) + ((dev & 0x1f) << 11) +\((fnc & 0x07) << 8) + (reg & ~(0x03)), PCI_INDEX);outw(value, PCI_DATA + (reg & 0x02));
}void
pciWrite32(unsigned char bus, unsigned char dev, unsigned char fnc, unsigned char reg, unsigned int value)
{outl((1 << 31) + (bus << 16) + ((dev & 0x1f) << 11) +\((fnc & 0x07) << 8) + (reg & ~(0x03)), PCI_INDEX);outl(value, PCI_DATA);
}int
main(int argc, char *argv[])
{int opt;extern char *optarg;extern int optind, opterr;int width = 1; /* default byte access */unsigned char bus, dev, fnc, reg;unsigned int wdata;while ((opt = getopt(argc, argv, "w:")) != -1) {if (opt == 'w') {width = atoi(optarg);} else {goto error;}}argc -= optind;argv += optind;iopl(3);if (argc == 4) {/* Read Pci */bus = strtoul(argv[0], NULL, 16);dev = strtoul(argv[1], NULL, 16);fnc = strtoul(argv[2], NULL, 16);reg = strtoul(argv[3], NULL, 16);if (width == 1) {printf("B:0x%02x/ D:0x%02x/ F:0x%02x/ R:0x%02x: 0x%02x\n",bus, dev, fnc, reg, pciRead8(bus, dev, fnc, reg));} else if (width == 2) {printf("B:0x%02x/ D:0x%02x/ F:0x%02x/ R:0x%02x: 0x%04x\n",bus, dev, fnc, reg, pciRead16(bus, dev, fnc, reg));} else if (width == 4) {printf("B:0x%02x/ D:0x%02x/ F:0x%02x/ R:0x%02x: 0x%08x\n",bus, dev, fnc, reg, pciRead32(bus, dev, fnc, reg));} else {goto error;}} else if (argc == 5) {/* Write Pci */bus = strtoul(argv[0], NULL, 16);dev = strtoul(argv[1], NULL, 16);fnc = strtoul(argv[2], NULL, 16);reg = strtoul(argv[3], NULL, 16);wdata = strtoul(argv[4], NULL, 16);if (width == 1) {pciWrite8(bus, dev, fnc, reg, wdata);} else if(width == 2) {pciWrite16(bus, dev, fnc, reg, wdata);} else if(width == 4) {pciWrite32(bus, dev, fnc, reg, wdata);} else {goto error;}} else {goto error;}return 0;error:printf("Usage: pci [-w WIDTH] BUS DEVICE FUNCTION REGISTER [DATA]\n""Pci configuration space read or write.\n"" -w number of byte width. permit 1(default), 2, 4\n""\n""This command executable only root user.\n""\n""Examples:\n"" pci 00 1f 00 00 Read pci from bus 0x00 dev 0x1f func 0x00 reg 0x00.\n"" pci -w2 00 1f 00 10 500 Write pci bus 0x00 dev 0x1f func 0x00 reg 0x10 to 0x500.\n""\n");return 1;
}