From e703628187342627270a83ea7bcfd3bb57ee1ad0 Mon Sep 17 00:00:00 2001 From: inexcode Date: Mon, 8 May 2023 17:57:16 +0300 Subject: [PATCH] PCI driver --- .idea/Linux.iml | 8 + .idea/conventionalCommit.xml | 10 ++ .idea/inspectionProfiles/Project_Default.xml | 16 ++ counter_reader/counter_reader_bash.service | 31 ++++ pci/Makefile | 7 + pci/ethernet.c | 164 +++++++++++++++++++ pci/read.py | 16 ++ shell.nix | 21 +++ 8 files changed, 273 insertions(+) create mode 100644 .idea/Linux.iml create mode 100644 .idea/conventionalCommit.xml create mode 100644 .idea/inspectionProfiles/Project_Default.xml create mode 100644 counter_reader/counter_reader_bash.service create mode 100644 pci/Makefile create mode 100644 pci/ethernet.c create mode 100644 pci/read.py create mode 100644 shell.nix diff --git a/.idea/Linux.iml b/.idea/Linux.iml new file mode 100644 index 0000000..ed671d8 --- /dev/null +++ b/.idea/Linux.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/conventionalCommit.xml b/.idea/conventionalCommit.xml new file mode 100644 index 0000000..2790c6f --- /dev/null +++ b/.idea/conventionalCommit.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..5ac4092 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,16 @@ + + + + \ No newline at end of file diff --git a/counter_reader/counter_reader_bash.service b/counter_reader/counter_reader_bash.service new file mode 100644 index 0000000..0cebf79 --- /dev/null +++ b/counter_reader/counter_reader_bash.service @@ -0,0 +1,31 @@ +[Unit] +# A short human readable title of the unit +Description=Counter reader in bash? +# A list of units whose activations will wait until after this unit has completed. +Before= +# A list of units whose activations will occur before this unit starts. +After=network.target +# A list of units to activate when this one is activated, if any unit listed here fails this unit will deactivate. +Requires= +# A list of units to activate when this one is activated, if a unit listed here fails this unit will continue to run. +Wants= + +[Service] +# Configures the process start-up type for this service unit, one of: +# simple - The process defined in ExecStart= will stay in the foreground while the unit is activated. +# forking - The process defined in ExecStart= will fork a background process and exit right away. +# oneshot - The process will exit right away, use with RemainAfterExit= to ensure the serice is marked as active. +# Consult the documentantion for types (https://www.freedesktop.org/software/systemd/man/systemd.service.html#Type=) other options. +Type=simple +# Command with arguments to invoke when the unit is activated. +ExecStart= +# Command with arguments to invoke when the unit is deactivated. +ExecStop= +# Configures under what conditions the unit will be restarted. +Restart=on-failure + +[Install] +# A list of units who when activated will try and activate this unit +WantedBy=multi-user.target +# A list of units to enable or disable when this unit is enabled or disabled (e.g., with systemctl enable) +Also= diff --git a/pci/Makefile b/pci/Makefile new file mode 100644 index 0000000..532d620 --- /dev/null +++ b/pci/Makefile @@ -0,0 +1,7 @@ +obj-m += ethernet.o +# make -C $(nix-build -E '(import {}).linux.dev' --no-out-link)/lib/modules/*/build M=$(pwd) + +all: + make -C /nix/store/f0b11y3qv1y0l3yvwkl88m181fnbmn80-linux-5.15.92-dev/lib/modules/*/build M=/home/inex/dev/Linux/pci modules +clean: + make -C /nix/store/f0b11y3qv1y0l3yvwkl88m181fnbmn80-linux-5.15.92-dev/lib/modules/*/build M=/home/inex/dev/Linux/pci clean diff --git a/pci/ethernet.c b/pci/ethernet.c new file mode 100644 index 0000000..c09c158 --- /dev/null +++ b/pci/ethernet.c @@ -0,0 +1,164 @@ +// A symbol PCI driver that outputs the MAC address of the network card: +#include +#include +#include + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Inex Code"); +MODULE_DESCRIPTION("A PCI driver"); +MODULE_VERSION("0.0.1"); + +#define VENDOR_ID 0x10ec +#define DEVICE_ID 0x8168 + +#define DRIVER_NAME "network_card_pci_driver_mac" + +#define CTL_GET_MAC _IOR('mac', 1, char *) + +static struct pci_device_id network_card_pci_driver_mac_id_table[] = { + { PCI_DEVICE(VENDOR_ID, DEVICE_ID) }, + { 0 } +}; + +MODULE_DEVICE_TABLE(pci, network_card_pci_driver_mac_id_table); + +static int network_card_pci_driver_mac_probe(struct pci_dev *dev, const struct pci_device_id *id); +static void network_card_pci_driver_mac_remove(struct pci_dev *dev); + +static struct pci_driver network_card_pci_driver_mac = { + .name = DRIVER_NAME, + .id_table = network_card_pci_driver_mac_id_table, + .probe = network_card_pci_driver_mac_probe, + .remove = network_card_pci_driver_mac_remove +}; + +static int network_card_open(struct inode *inode, struct file *file); +static int network_card_release(struct inode *inode, struct file *file); +static ssize_t network_card_ioctl(struct file *file, unsigned int cmd, unsigned long arg); + +static struct file_operations network_card_fops = { + .owner = THIS_MODULE, + .open = network_card_open, + .release = network_card_release, + .unlocked_ioctl = network_card_ioctl +}; + +static int Major; +static struct class *network_card_class; + +unsigned char mac_addr[6]; + +static atomic_t already_open = ATOMIC_INIT(0); + +static int __init network_card_pci_driver_mac_init(void) { + int register_result = pci_register_driver(&network_card_pci_driver_mac); + if (register_result < 0) { + printk(KERN_ERR + "pci_register_driver failed\n"); + return register_result; + } + + Major = register_chrdev(0, DRIVER_NAME, &network_card_fops); + if (Major < 0) { + printk(KERN_ERR + "register_chrdev failed\n"); + return Major; + } + + network_card_class = class_create(THIS_MODULE, DRIVER_NAME); + if (!network_card_class) { + printk(KERN_ERR + "class_create failed\n"); + return -1; + } + + device_create(network_card_class, NULL, MKDEV(Major, 0), NULL, DRIVER_NAME); + + return 0; +} + +static void __exit network_card_pci_driver_mac_exit(void) { + class_destroy(network_card_class); + unregister_chrdev(Major, DRIVER_NAME); + pci_unregister_driver(&network_card_pci_driver_mac); + + printk(KERN_INFO + "Goodbye cruel world.\n"); + + return; +} + +static int network_card_pci_driver_mac_probe(struct pci_dev *dev, const struct pci_device_id *id) { + u8 __iomem *mmio_base; + + int bar = 2; + + if (pci_resource_flags(dev, bar) & IORESOURCE_MEM) { + mmio_base = pci_iomap(dev, bar, pci_resource_len(dev, bar)); + if (!mmio_base) { + printk(KERN_ERR + "pci_iomap failed\n"); + return -1; + } + } else { + printk(KERN_ERR + "Not a memory-mapped resource\n"); + return -1; + } + + int i; + for (i = 0; i < 6; i++) { + mac_addr[i] = ioread8(mmio_base + i); + printk(KERN_INFO + "MAC address byte %d: %02x\n", i, mmio_base[i]); + } + + iounmap(mmio_base); + + return 0; +} + +static void network_card_pci_driver_mac_remove(struct pci_dev *dev) { + dev_t devno = MKDEV(Major, 0); + device_destroy(network_card_class, devno) +} + +static int network_card_open(struct inode *inode, struct file *file) { + if (atomic_cmpxchg(&already_open, 0, 1)) { + printk(KERN_ERR + "already_open is true\n"); + return -EBUSY; + } + + try_module_get(THIS_MODULE); + return 0; +} + +static int network_card_release(struct inode *inode, struct file *file) { + atomic_set(&already_open, 0); + module_put(THIS_MODULE); + + return 0; +} + + +static ssize_t network_card_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { + switch (cmd) { + case CTL_GET_MAC: + if (copy_to_user((unsigned long __user *) arg, mac_addr, 6) != 0) { + printk(KERN_ERR + "copy_to_user failed\n"); + return -EFAULT; + } + break; + default: + printk(KERN_ERR + "unknown ioctl\n"); + return -EINVAL; + } + + return 0; +} + +module_init(network_card_pci_driver_mac_init); +module_exit(network_card_pci_driver_mac_exit); diff --git a/pci/read.py b/pci/read.py new file mode 100644 index 0000000..0ed0320 --- /dev/null +++ b/pci/read.py @@ -0,0 +1,16 @@ +import fcntl + +MAC_ADDRESS_SIZE = 6 +DEVICE_PATH = "/dev/network_card_pci_driver_mac" +MY_IOCTL_GET_MAC_ADDRESS = 0xed696301 + +if __name__ == "__main__": + device_file = open(DEVICE_PATH, "rb") + + mac_address_buffer = bytearray(MAC_ADDRESS_SIZE) + + fcntl.ioctl(device_file, MY_IOCTL_GET_MAC_ADDRESS, mac_address_buffer) + + print(mac_address_buffer.hex()) + + device_file.close() diff --git a/shell.nix b/shell.nix new file mode 100644 index 0000000..25160de --- /dev/null +++ b/shell.nix @@ -0,0 +1,21 @@ +with import {}; +stdenv.mkDerivation { + name = "env"; + nativeBuildInputs = [ pkg-config ]; + buildInputs = [ + cryptsetup + dbus + systemd + libcap + libgcrypt + xz + zstd + lz4 + libgpg-error + libnotify + gdk-pixbuf + glib + glibc + + ]; +} \ No newline at end of file