5

I'm trying to create a character device driver on Minix. I would like it to be able to accept read() and write() calls. My understanding is that I would need to use sys_safecopyfrom() for the function which runs the read() function and sys_safecopyto() for the function which runs the write() function. The issue is that I keep getting a similar error (although not exactly the same, but I think that the differences are memory locations) when I run it like this. The error is:

verify_grant: grant verify failed: access invalid: want 0x..., have 0x...
grant 2 verify to copy ... -> ... by ... failed err -1
read: Operation not permitted

The "..." are memory locations and the error is similar for write except for the memory locations and it says "write" instead of "read" on the last line.

I think that the relevant code is the following:

#include <minix/drivers.h>
#include <minix/chardriver.h>
#include <stdio.h>
#include <stdlib.h>
#include <minix/ds.h>
...
static struct chardriver hello_tab =
{
    .cdr_open   = hello_open,
    .cdr_close  = hello_close,
    .cdr_read   = hello_read,
    .cdr_write  = hello_write,
};
...
static ssize_t hello_read(devminor_t UNUSED(minor), u64_t position,
    endpoint_t endpt, cp_grant_id_t grant, size_t size, int UNUSED(flags),
    cdev_id_t UNUSED(id))
{
    u64_t dev_size;
    char *ptr;
    int ret;
    char *buf = HELLO_MESSAGE;

    printf("hello_read()\n");

    /* This is the total size of our device. */
    dev_size = (u64_t) strlen(buf);

    /* Check for EOF, and possibly limit the read size. */
    if (position >= dev_size) return 0;     /* EOF */
    if (position + size > dev_size)
        size = (size_t)(dev_size - position);   /* limit size */

    /* Copy the requested part to the caller. */
    ptr = buf + (size_t)position;
    if ((ret = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) ptr, size)) != OK)
        return ret;

    /* Return the number of bytes read. */
    printf("Message is :%s", ptr);
    return size;
}
static ssize_t hello_write(devminor_t UNUSED(minor), u64_t position,
    endpoint_t endpt, cp_grant_id_t grant, size_t size, int UNUSED(flags),
    cdev_id_t UNUSED(id))
{
    u64_t dev_size;
    char *ptr;
    int ret;
    char *buf = HELLO_MESSAGE;

    printf("hello_write()\n");

    /* This is the total size of our device. */
    dev_size = (u64_t) strlen(buf);

    /* Check for EOF, and possibly limit the read size. */
    if (position >= dev_size) return 0;     /* EOF */
    if (position + size > dev_size)
        size = (size_t)(dev_size - position);   /* limit size */

    /* Copy the requested part to the caller. */
    ptr = buf + (size_t)position;
    if ((ret = sys_safecopyto(endpt, grant, 0, (vir_bytes) ptr, size)) != OK)
        return ret;

    /* Return the number of bytes read. */
    return size;
}

The hello_read function is based off of the hello_write functions but I think that it should still work and should read the information into ptr.

Also, I'm a bit hazy on how I would go about getting the second argument in the write() function (the buffer) in my hello_write() function. Is it contained in one of hello_read()'s arguments?

Thanks for your help!

Federico
  • 3,782
  • 32
  • 46
David
  • 1,398
  • 1
  • 14
  • 20

1 Answers1

0

So, I know it's been a long time and there's no activity here but I thought I would answer the question.

I am going to start by saying the the error occurs when passing the wrong arguments into sys_safecopyto/from.

Now to really debug this I would want to see the rest of the code you had. But for anyone else who comes across this problem I'm going to give some tips

  • look at how many bytes you are passing the the sys_safecopy funcitons
  • make sure you are putting the correct offset with the buffer when writing. For the case I used it in that was (buffer_ptr + current_size)
  • make sure if you are using an earlier version of minix that you are putting in the correct amount of parameters into the sys_safecopy funcitons (could be 5 args or 6 args, the last one on older versions of minix for the hello driver would just be "D" ;) )