1 /* 2 * Copyright 2007, Haiku, Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include <Drivers.h> 8 #include <KernelExport.h> 9 #include <string.h> 10 #include <unistd.h> 11 #include <sys/types.h> 12 13 #define DRIVER_NAME "mem" 14 #define DEVICE_NAME "misc/mem" 15 16 #define DEVMNT "/dev/" 17 18 /* also publish /dev/mem */ 19 #define PUBLISH_DEV_MEM 20 21 static status_t mem_open(const char*, uint32, void**); 22 static status_t mem_close(void*); 23 static status_t mem_free(void*); 24 //static status_t mem_control(void*, uint32, void*, size_t); 25 static status_t mem_read(void*, off_t, void*, size_t*); 26 static status_t mem_write(void*, off_t, const void*, size_t*); 27 28 static area_id mem_map_target(off_t position, size_t len, uint32 protection, void **va); 29 30 static const char* mem_name[] = { 31 DEVICE_NAME, 32 #ifdef PUBLISH_DEV_MEM 33 DRIVER_NAME, 34 #endif 35 NULL 36 }; 37 38 39 device_hooks mem_hooks = { 40 mem_open, 41 mem_close, 42 mem_free, 43 NULL, /*mem_control,*/ 44 mem_read, 45 mem_write, 46 }; 47 48 int32 api_version = B_CUR_DRIVER_API_VERSION; 49 50 status_t 51 init_hardware(void) 52 { 53 return B_OK; 54 } 55 56 57 status_t 58 init_driver(void) 59 { 60 return B_OK; 61 } 62 63 64 void 65 uninit_driver(void) 66 { 67 } 68 69 70 const char** 71 publish_devices(void) 72 { 73 return mem_name; 74 } 75 76 77 device_hooks* 78 find_device(const char* name) 79 { 80 return &mem_hooks; 81 } 82 83 84 status_t 85 mem_open(const char* name, uint32 flags, void** cookie) 86 { 87 // not really needed. 88 *cookie = NULL; 89 90 return B_OK; 91 } 92 93 94 status_t 95 mem_close(void* cookie) 96 { 97 return B_OK; 98 } 99 100 101 status_t 102 mem_free(void* cookie) 103 { 104 return B_OK; 105 } 106 107 /* 108 status_t 109 mem_control(void* cookie, uint32 op, void* arg, size_t length) 110 { 111 return ENOSYS; 112 } 113 */ 114 115 status_t 116 mem_read(void* cookie, off_t position, void* buffer, size_t* numBytes) 117 { 118 status_t err; 119 void *va; 120 area_id area; 121 122 /* check perms */ 123 err = EPERM; 124 if (getuid() != 0 && geteuid() != 0) 125 goto err1; 126 err = area = mem_map_target(position, *numBytes, B_READ_AREA, &va); 127 if (err < 0) 128 goto err1; 129 memcpy(buffer, va, *numBytes); 130 delete_area(area); 131 return B_OK; 132 err1: 133 *numBytes = 0; 134 return err; 135 } 136 137 138 status_t 139 mem_write(void* cookie, off_t position, const void* buffer, size_t* numBytes) 140 { 141 status_t err; 142 void *va; 143 area_id area; 144 145 /* check perms */ 146 err = EPERM; 147 if (getuid() != 0 && geteuid() != 0) 148 goto err1; 149 err = area = mem_map_target(position, *numBytes, B_WRITE_AREA, &va); 150 if (err < 0) 151 goto err1; 152 memcpy(va, buffer, *numBytes); 153 delete_area(area); 154 return B_OK; 155 err1: 156 *numBytes = 0; 157 return err; 158 } 159 160 area_id 161 mem_map_target(off_t position, size_t len, uint32 protection, void **va) 162 { 163 area_id area; 164 void *paddr; 165 void *vaddr; 166 int offset; 167 size_t size; 168 169 /* SIZE_MAX actually but 2G should be enough anyway */ 170 if (len > SSIZE_MAX - B_PAGE_SIZE) 171 return EINVAL; 172 173 /* the first page address */ 174 paddr = (void *)(addr_t)(position & ~((off_t)B_PAGE_SIZE - 1)); 175 /* offset of target into it */ 176 offset = position - (off_t)(addr_t)paddr; 177 /* size of the whole mapping (page rounded) */ 178 size = (offset + len + B_PAGE_SIZE - 1) & ~((size_t)B_PAGE_SIZE - 1); 179 180 area = map_physical_memory("mem_driver_temp", 181 paddr, size, B_ANY_KERNEL_ADDRESS, 182 protection, &vaddr); 183 184 if (area < 0) 185 return area; 186 187 *va = vaddr + offset; 188 189 return EINVAL; 190 } 191