* Fix the mem driver to not always return invalid argument

* Cleanup

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@23140 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Lotz
2007-12-18 18:48:50 +00:00
parent 35f6af0388
commit 9e0b9fbda5
+50 -59
View File
@@ -2,8 +2,6 @@
* Copyright 2007, Haiku, Inc. All rights reserved. * Copyright 2007, Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#include <Drivers.h> #include <Drivers.h>
#include <KernelExport.h> #include <KernelExport.h>
#include <string.h> #include <string.h>
@@ -21,11 +19,11 @@
static status_t mem_open(const char*, uint32, void**); static status_t mem_open(const char*, uint32, void**);
static status_t mem_close(void*); static status_t mem_close(void*);
static status_t mem_free(void*); static status_t mem_free(void*);
//static status_t mem_control(void*, uint32, void*, size_t);
static status_t mem_read(void*, off_t, void*, size_t*); static status_t mem_read(void*, off_t, void*, size_t*);
static status_t mem_write(void*, off_t, const void*, size_t*); static status_t mem_write(void*, off_t, const void*, size_t*);
static area_id mem_map_target(off_t position, size_t len, uint32 protection, void **va); static area_id mem_map_target(off_t position, size_t length, uint32 protection,
void **virtualAddress);
static const char* mem_name[] = { static const char* mem_name[] = {
DEVICE_NAME, DEVICE_NAME,
@@ -86,7 +84,6 @@ mem_open(const char* name, uint32 flags, void** cookie)
{ {
// not really needed. // not really needed.
*cookie = NULL; *cookie = NULL;
return B_OK; return B_OK;
} }
@@ -104,87 +101,81 @@ mem_free(void* cookie)
return B_OK; return B_OK;
} }
/*
status_t
mem_control(void* cookie, uint32 op, void* arg, size_t length)
{
return ENOSYS;
}
*/
status_t status_t
mem_read(void* cookie, off_t position, void* buffer, size_t* numBytes) mem_read(void* cookie, off_t position, void* buffer, size_t* numBytes)
{ {
status_t err; void *virtualAddress;
void *va;
area_id area; area_id area;
/* check perms */ /* check permissions */
err = EPERM; if (getuid() != 0 && geteuid() != 0) {
if (getuid() != 0 && geteuid() != 0) *numBytes = 0;
goto err1; return EPERM;
err = area = mem_map_target(position, *numBytes, B_READ_AREA, &va); }
if (err < 0)
goto err1; area = mem_map_target(position, *numBytes, B_READ_AREA, &virtualAddress);
memcpy(buffer, va, *numBytes); if (area < 0) {
*numBytes = 0;
return area;
}
memcpy(buffer, virtualAddress, *numBytes);
delete_area(area); delete_area(area);
return B_OK; return B_OK;
err1:
*numBytes = 0;
return err;
} }
status_t status_t
mem_write(void* cookie, off_t position, const void* buffer, size_t* numBytes) mem_write(void* cookie, off_t position, const void* buffer, size_t* numBytes)
{ {
status_t err; void *virtualAddress;
void *va;
area_id area; area_id area;
/* check perms */ /* check permissions */
err = EPERM; if (getuid() != 0 && geteuid() != 0) {
if (getuid() != 0 && geteuid() != 0) *numBytes = 0;
goto err1; return EPERM;
err = area = mem_map_target(position, *numBytes, B_WRITE_AREA, &va); }
if (err < 0)
goto err1; area = mem_map_target(position, *numBytes, B_WRITE_AREA, &virtualAddress);
memcpy(va, buffer, *numBytes); if (area < 0) {
*numBytes = 0;
return area;
}
memcpy(virtualAddress, buffer, *numBytes);
delete_area(area); delete_area(area);
return B_OK; return B_OK;
err1:
*numBytes = 0;
return err;
} }
area_id area_id
mem_map_target(off_t position, size_t len, uint32 protection, void **va) mem_map_target(off_t position, size_t length, uint32 protection,
void **virtualAddress)
{ {
area_id area; area_id area;
void *paddr; void *physicalAddress;
void *vaddr; size_t offset;
int offset;
size_t size; size_t size;
/* SIZE_MAX actually but 2G should be enough anyway */ /* SIZE_MAX actually but 2G should be enough anyway */
if (len > SSIZE_MAX - B_PAGE_SIZE) if (length > SSIZE_MAX - B_PAGE_SIZE)
return EINVAL; return EINVAL;
/* the first page address */ /* the first page address */
paddr = (void *)(addr_t)(position & ~((off_t)B_PAGE_SIZE - 1)); physicalAddress = (void *)(addr_t)(position & ~((off_t)B_PAGE_SIZE - 1));
/* offset of target into it */ /* offset of target into it */
offset = position - (off_t)(addr_t)paddr; offset = position - (off_t)(addr_t)physicalAddress;
/* size of the whole mapping (page rounded) */ /* size of the whole mapping (page rounded) */
size = (offset + len + B_PAGE_SIZE - 1) & ~((size_t)B_PAGE_SIZE - 1); size = (offset + length + B_PAGE_SIZE - 1) & ~((size_t)B_PAGE_SIZE - 1);
area = map_physical_memory("mem_driver_temp", physicalAddress, size,
area = map_physical_memory("mem_driver_temp", B_ANY_KERNEL_ADDRESS, protection, virtualAddress);
paddr, size, B_ANY_KERNEL_ADDRESS,
protection, &vaddr);
if (area < 0) if (area < 0)
return area; return area;
*va = vaddr + offset; *virtualAddress += offset;
return area;
return EINVAL;
} }