xref: /haiku/src/add-ons/kernel/drivers/misc/mem.c (revision f09ba8ea46ba2f4e482d7cd03e8eb77f37a60663)
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