commit 04e0949162192da2d8a569a0b402253876e23ca4 Author: Roman Hargrave Date: Sun Aug 30 10:47:29 2015 -0500 Initial commit diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..8b2c653 --- /dev/null +++ b/Makefile @@ -0,0 +1,22 @@ +ifndef KERNEL +KERNEL = /lib/modules/$(shell uname -r)/build +endif +EXTRA_CFLAGS := -Wall -Wstrict-prototypes -O2 -fno-strict-aliasing +obj-m += amifldrv_mod.o +amifldrv_mod-objs := amifldrv.o amiwrap.o +default: + make -C $(KERNEL) SUBDIRS=$(PWD) modules + rm -f amifldrv.o_shipped + mv amifldrv.o amifldrv.o_shipped + rm -f amifldrv_mod.o + mv amifldrv_mod.ko ../amifldrv_mod +.PHONY : clean +clean: + rm -f *.*~ + rm -f test + rm -f .*cmd + rm -f *.o + rm -f *mod* + rm -f *.ko + rm -f amifldrv.o_shipped + rm -rf .tmp_versions/ diff --git a/amifldrv.c b/amifldrv.c new file mode 100644 index 0000000..c4ac199 --- /dev/null +++ b/amifldrv.c @@ -0,0 +1,191 @@ +#include +#include +#include +#include +#include "amifldrv.h" +#include "amiwrap.h" +int amifldrv_ioctl(void); +int amifldrv_mmap(void); +static int *kmalloc_area = NULL; +static int *kmalloc_ptr = NULL; +static unsigned long kmalloc_len = 0L; +static int major; +static AMIFLDRV_ALLOC kmalloc_drv[128]; +static int kcount = 0; +static int amifldrv_init_module(void) +{ + ulArg0 = 0; + pvArg0 = &amifldrv_fops; + if ((major=wrap_register_chrdev()) < 0) { + return (-EIO); + } + memset(kmalloc_drv, 0, sizeof(AMIFLDRV_ALLOC) * 128); + return(0); +} +static void amifldrv_cleanup_module(void) +{ + unsigned long virt_addr; + int iloop = 0; + if (kcount > 0) { + for (iloop=0; iloop= 128) return -EINVAL; + kmalloc_ptr = NULL; + if (!arg || kmalloc_ptr) { + return -EINVAL; + } + pvArg0 = (void*)&arg_kernel_space; + pvArg1 = (void*)arg; + ulArg0 = sizeof(AMIFLDRV_ALLOC); + wrap_copy_from_user(); + if (arg_kernel_space.size > 128*1024) return -EINVAL; + kmalloc_len = ((arg_kernel_space.size + PAGE_SIZE -1) & PAGE_MASK); + ulArg0 = kmalloc_len+2*PAGE_SIZE; + ulArg1 = GFP_DMA|GFP_KERNEL; + kmalloc_ptr = wrap_kmalloc(); + kmalloc_area=(int *)(((unsigned long)kmalloc_ptr + PAGE_SIZE -1) & PAGE_MASK); + for (virt_addr=(unsigned long)kmalloc_area; virt_addr<(unsigned long)kmalloc_area+kmalloc_len; virt_addr+=PAGE_SIZE) + { + ulArg0 = virt_addr; + pvArg0 = wrap_virt_to_page(); + wrap_mem_map_reserve(); + } + for (i=0; i<(kmalloc_len/sizeof(int)); i++) { + kmalloc_area[i]=(0xafd0<<16) +i; + } + kmalloc_drv[kcount].size = arg_kernel_space.size; + kmalloc_drv[kcount].kmallocptr = kmalloc_ptr; + kmalloc_drv[kcount].kvirtlen = kmalloc_len; + kmalloc_drv[kcount].kvirtadd = kmalloc_area; + kmalloc_drv[kcount].kphysadd = (void *)((unsigned long)virt_to_phys(kmalloc_area)); + kcount++; + arg_kernel_space.kvirtadd = kmalloc_area; + arg_kernel_space.kphysadd = (void *)((unsigned long)virt_to_phys(kmalloc_area)); + pvArg0 = (void*)arg; + pvArg1 = (void*)&arg_kernel_space; + ulArg0 = sizeof(AMIFLDRV_ALLOC); + wrap_copy_to_user(); + return 0; + } + case CMD_FREE: + { + unsigned long virt_addr; + AMIFLDRV_ALLOC arg_kernel_space; + int isearch = 0; + pvArg0 = (void*)&arg_kernel_space; + pvArg1 = (void*)arg; + ulArg0 = sizeof(AMIFLDRV_ALLOC); + wrap_copy_from_user(); + if (kcount > 0) { + for (isearch=0; isearch= kcount) return 0; + kmalloc_ptr = kmalloc_drv[isearch].kmallocptr; + kmalloc_area = kmalloc_drv[isearch].kvirtadd; + kmalloc_len = kmalloc_drv[isearch].kvirtlen; + } else + return 0; + if (kmalloc_ptr) { + for(virt_addr=(unsigned long)kmalloc_area; virt_addr<(unsigned long)kmalloc_area+kmalloc_len; virt_addr+=PAGE_SIZE) + { + ulArg0 = virt_addr; + pvArg0 = wrap_virt_to_page(); + wrap_mem_map_unreserve(); + } + if (kmalloc_ptr) { + pvArg0 = kmalloc_ptr; + wrap_kfree(); + } + kmalloc_len = 0L; + kmalloc_ptr = NULL; + kmalloc_area = NULL; + kcount--; + if (isearch != kcount) { + kmalloc_drv[isearch].size = kmalloc_drv[kcount].size; + kmalloc_drv[isearch].kmallocptr = kmalloc_drv[kcount].kmallocptr; + kmalloc_drv[isearch].kvirtlen = kmalloc_drv[kcount].kvirtlen; + kmalloc_drv[isearch].kvirtadd = kmalloc_drv[kcount].kvirtadd; + kmalloc_drv[isearch].kphysadd = kmalloc_drv[kcount].kphysadd; + } + kmalloc_drv[kcount].size = 0; + kmalloc_drv[kcount].kmallocptr = NULL; + kmalloc_drv[kcount].kvirtlen = 0; + kmalloc_drv[kcount].kvirtadd = NULL; + kmalloc_drv[kcount].kphysadd = NULL; + } + return 0; + } + case CMD_LOCK_KB: + disable_irq(1); + return 0; + case CMD_UNLOCK_KB: + enable_irq(1); + return 0; + } + return -ENOTTY; +} +int amifldrv_mmap(void) +{ + struct vm_area_struct *vma = (struct vm_area_struct *)pvArg1; + unsigned long offset = vma->vm_pgoff<vm_end - vma->vm_start; + if (offset & ~PAGE_MASK) { + return -ENXIO; + } + if (!kmalloc_ptr) { + return(-ENXIO); + } + if (size>kmalloc_len) { + return(-ENXIO); + } + if ((offset+size)>kmalloc_len) { + return -ENXIO; + } + if ((vma->vm_flags & VM_WRITE) && !(vma->vm_flags & VM_SHARED)) { + return(-EINVAL); + } + vma->vm_flags |= VM_LOCKED; + pvArg0 = vma; + ulArg0 = vma->vm_start; + ulArg1 = virt_to_phys((void*)((unsigned long)kmalloc_area)); + ulArg2 = size; + pgArg0 = PAGE_SHARED; + if (wrap_remap_page_range()) { + return -ENXIO; + } + return(0); +} diff --git a/amifldrv.h b/amifldrv.h new file mode 100644 index 0000000..bb4eaba --- /dev/null +++ b/amifldrv.h @@ -0,0 +1,13 @@ +extern struct file_operations amifldrv_fops; +#define CMD_ALLOC 0x4160 +#define CMD_FREE 0x4161 +#define CMD_LOCK_KB 0x4162 +#define CMD_UNLOCK_KB 0x4163 +typedef struct tagAMIFLDRV_ALLOC +{ + long size; + unsigned long kvirtlen; + void * kmallocptr; + void * kvirtadd; + void * kphysadd; +} AMIFLDRV_ALLOC; diff --git a/amiwrap.c b/amiwrap.c new file mode 100644 index 0000000..533fd0b --- /dev/null +++ b/amiwrap.c @@ -0,0 +1,191 @@ +//------------------------------------------------------------------------------------------------- +// AMI Firmware Update Utility(APTIO) v5.05.04 +// Copyright (C)2011 American Megatrends Inc. All Rights Reserved. +//------------------------------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) +#include +#endif +#include "amiwrap.h" + +extern int amifldrv_ioctl(void); +extern int amifldrv_mmap(void); +unsigned long ulArg0; +unsigned long ulArg1; +unsigned long ulArg2; +pgprot_t pgArg0; +void *pvArg0; +void *pvArg1; + +AFU_ATTRIBUTE_FUNC static int wrap_open(struct inode *inode, struct file *file); +AFU_ATTRIBUTE_FUNC static int wrap_release(struct inode *inode, struct file *file); +#if defined(HAVE_UNLOCKED_IOCTL) +AFU_ATTRIBUTE_FUNC static long wrap_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); +#else +AFU_ATTRIBUTE_FUNC static int wrap_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); +#endif +AFU_ATTRIBUTE_FUNC static int wrap_mmap(struct file *file, struct vm_area_struct *vma); + +struct file_operations amifldrv_fops = +{ +owner: + THIS_MODULE, +open: + wrap_open, +release: + wrap_release, +#if defined(HAVE_UNLOCKED_IOCTL) +unlocked_ioctl: + wrap_unlocked_ioctl, +#else +ioctl: + wrap_ioctl, +#endif +mmap: + wrap_mmap, +}; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) +#define mem_map_reserve(p) set_bit(PG_reserved, &((p)->flags)) +#define mem_map_unreserve(p) clear_bit(PG_reserved, &((p)->flags)) +MODULE_AUTHOR("American Megatrends Inc."); +MODULE_DESCRIPTION("AMI Flash Update utility driver"); +MODULE_LICENSE("Proprietary"); +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) +static int device_open_count = 0; +#endif + +AFU_ATTRIBUTE_FUNC +int wrap_open(struct inode *inode, struct file *file) +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) + MOD_INC_USE_COUNT; +#else + if (device_open_count) + return -EBUSY; + device_open_count++; + try_module_get(THIS_MODULE); +#endif + return(0); +} + +AFU_ATTRIBUTE_FUNC +int wrap_release(struct inode *inode, struct file *file) +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) + MOD_DEC_USE_COUNT; +#else + device_open_count--; + module_put(THIS_MODULE); +#endif + return(0); +} + +AFU_ATTRIBUTE_FUNC +#if defined(HAVE_UNLOCKED_IOCTL) +long wrap_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +#else +int wrap_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) +#endif +{ +#ifndef HAVE_UNLOCKED_IOCTL + pvArg0 = inode; +#endif + pvArg1 = filp; + ulArg0 = cmd; + ulArg1 = arg; +#if defined(HAVE_UNLOCKED_IOCTL) + return (long)amifldrv_ioctl(); +#else + return amifldrv_ioctl(); +#endif +} + +AFU_ATTRIBUTE_FUNC +int wrap_mmap(struct file *file, struct vm_area_struct *vma) +{ + pvArg0 = file; + pvArg1 = vma; + return amifldrv_mmap(); +} + +AFU_ATTRIBUTE_FUNC +int wrap_register_chrdev() +{ + return register_chrdev((unsigned int)ulArg0, "amifldrv", (struct file_operations *)pvArg0); +} + +AFU_ATTRIBUTE_FUNC +void wrap_unregister_chrdev() +{ + unregister_chrdev((unsigned int)ulArg0, "amifldrv"); +} + +AFU_ATTRIBUTE_FUNC +void wrap_mem_map_reserve() +{ + mem_map_reserve((struct page*)pvArg0); +} + +AFU_ATTRIBUTE_FUNC +void wrap_mem_map_unreserve() +{ + mem_map_unreserve((struct page*)pvArg0); +} + +AFU_ATTRIBUTE_FUNC +struct page *wrap_virt_to_page() +{ + return virt_to_page(ulArg0); +} + +AFU_ATTRIBUTE_FUNC +int wrap_remap_page_range() +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) + ulArg1 = ulArg1>>PAGE_SHIFT; + return remap_pfn_range((struct vm_area_struct *)pvArg0, ulArg0, ulArg1, ulArg2, pgArg0); +#else + return remap_page_range((struct vm_area_struct *)pvArg0, ulArg0, ulArg1, ulArg2, pgArg0); +#endif +} + +AFU_ATTRIBUTE_FUNC +void *wrap_kmalloc() +{ + return kmalloc((size_t)ulArg0, (int)ulArg1); +} + +AFU_ATTRIBUTE_FUNC +void wrap_kfree() +{ + kfree(pvArg0); +} + +AFU_ATTRIBUTE_FUNC +unsigned long wrap_copy_from_user() +{ + return copy_from_user(pvArg0, pvArg1, ulArg0); +} + +AFU_ATTRIBUTE_FUNC +unsigned long wrap_copy_to_user() +{ + return copy_to_user(pvArg0, pvArg1, ulArg0); +} + diff --git a/amiwrap.h b/amiwrap.h new file mode 100644 index 0000000..b47039a --- /dev/null +++ b/amiwrap.h @@ -0,0 +1,21 @@ +//------------------------------------------------------------------------------------------------- +// AMI Firmware Update Utility(APTIO) v5.05.04 +// Copyright (C)2011 American Megatrends Inc. All Rights Reserved. +//------------------------------------------------------------------------------------------------- +#define AFU_ATTRIBUTE_FUNC +AFU_ATTRIBUTE_FUNC int wrap_register_chrdev(void); +AFU_ATTRIBUTE_FUNC void wrap_unregister_chrdev(void); +AFU_ATTRIBUTE_FUNC void wrap_mem_map_reserve(void); +AFU_ATTRIBUTE_FUNC void wrap_mem_map_unreserve(void); +AFU_ATTRIBUTE_FUNC int wrap_remap_page_range(void); +AFU_ATTRIBUTE_FUNC struct page *wrap_virt_to_page(void); +AFU_ATTRIBUTE_FUNC void *wrap_kmalloc(void); +AFU_ATTRIBUTE_FUNC void wrap_kfree(void); +AFU_ATTRIBUTE_FUNC unsigned long wrap_copy_from_user(void); +AFU_ATTRIBUTE_FUNC unsigned long wrap_copy_to_user(void); +extern unsigned long ulArg0; +extern unsigned long ulArg1; +extern unsigned long ulArg2; +extern pgprot_t pgArg0; +extern void *pvArg0; +extern void *pvArg1;