* 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:
parent
35f6af0388
commit
9e0b9fbda5
@ -2,8 +2,6 @@
|
||||
* Copyright 2007, Haiku, Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include <Drivers.h>
|
||||
#include <KernelExport.h>
|
||||
#include <string.h>
|
||||
@ -21,11 +19,11 @@
|
||||
static status_t mem_open(const char*, uint32, void**);
|
||||
static status_t mem_close(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_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[] = {
|
||||
DEVICE_NAME,
|
||||
@ -86,7 +84,6 @@ mem_open(const char* name, uint32 flags, void** cookie)
|
||||
{
|
||||
// not really needed.
|
||||
*cookie = NULL;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@ -104,87 +101,81 @@ mem_free(void* cookie)
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
status_t
|
||||
mem_control(void* cookie, uint32 op, void* arg, size_t length)
|
||||
{
|
||||
return ENOSYS;
|
||||
}
|
||||
*/
|
||||
|
||||
status_t
|
||||
mem_read(void* cookie, off_t position, void* buffer, size_t* numBytes)
|
||||
{
|
||||
status_t err;
|
||||
void *va;
|
||||
void *virtualAddress;
|
||||
area_id area;
|
||||
|
||||
/* check perms */
|
||||
err = EPERM;
|
||||
if (getuid() != 0 && geteuid() != 0)
|
||||
goto err1;
|
||||
err = area = mem_map_target(position, *numBytes, B_READ_AREA, &va);
|
||||
if (err < 0)
|
||||
goto err1;
|
||||
memcpy(buffer, va, *numBytes);
|
||||
|
||||
/* check permissions */
|
||||
if (getuid() != 0 && geteuid() != 0) {
|
||||
*numBytes = 0;
|
||||
return EPERM;
|
||||
}
|
||||
|
||||
area = mem_map_target(position, *numBytes, B_READ_AREA, &virtualAddress);
|
||||
if (area < 0) {
|
||||
*numBytes = 0;
|
||||
return area;
|
||||
}
|
||||
|
||||
memcpy(buffer, virtualAddress, *numBytes);
|
||||
delete_area(area);
|
||||
return B_OK;
|
||||
err1:
|
||||
*numBytes = 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
mem_write(void* cookie, off_t position, const void* buffer, size_t* numBytes)
|
||||
{
|
||||
status_t err;
|
||||
void *va;
|
||||
void *virtualAddress;
|
||||
area_id area;
|
||||
|
||||
/* check perms */
|
||||
err = EPERM;
|
||||
if (getuid() != 0 && geteuid() != 0)
|
||||
goto err1;
|
||||
err = area = mem_map_target(position, *numBytes, B_WRITE_AREA, &va);
|
||||
if (err < 0)
|
||||
goto err1;
|
||||
memcpy(va, buffer, *numBytes);
|
||||
|
||||
/* check permissions */
|
||||
if (getuid() != 0 && geteuid() != 0) {
|
||||
*numBytes = 0;
|
||||
return EPERM;
|
||||
}
|
||||
|
||||
area = mem_map_target(position, *numBytes, B_WRITE_AREA, &virtualAddress);
|
||||
if (area < 0) {
|
||||
*numBytes = 0;
|
||||
return area;
|
||||
}
|
||||
|
||||
memcpy(virtualAddress, buffer, *numBytes);
|
||||
delete_area(area);
|
||||
return B_OK;
|
||||
err1:
|
||||
*numBytes = 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
void *paddr;
|
||||
void *vaddr;
|
||||
int offset;
|
||||
void *physicalAddress;
|
||||
size_t offset;
|
||||
size_t size;
|
||||
|
||||
|
||||
/* 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;
|
||||
|
||||
|
||||
/* 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 = position - (off_t)(addr_t)paddr;
|
||||
offset = position - (off_t)(addr_t)physicalAddress;
|
||||
|
||||
/* size of the whole mapping (page rounded) */
|
||||
size = (offset + len + B_PAGE_SIZE - 1) & ~((size_t)B_PAGE_SIZE - 1);
|
||||
|
||||
area = map_physical_memory("mem_driver_temp",
|
||||
paddr, size, B_ANY_KERNEL_ADDRESS,
|
||||
protection, &vaddr);
|
||||
|
||||
size = (offset + length + B_PAGE_SIZE - 1) & ~((size_t)B_PAGE_SIZE - 1);
|
||||
area = map_physical_memory("mem_driver_temp", physicalAddress, size,
|
||||
B_ANY_KERNEL_ADDRESS, protection, virtualAddress);
|
||||
if (area < 0)
|
||||
return area;
|
||||
|
||||
*va = vaddr + offset;
|
||||
|
||||
return EINVAL;
|
||||
|
||||
*virtualAddress += offset;
|
||||
return area;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user