mirror of
https://github.com/drasko/codezero.git
synced 2026-01-12 02:43:15 +01:00
Added an extended ipc return library function.
This commit is contained in:
@@ -110,6 +110,23 @@ static inline void l4_set_tag(unsigned int tag)
|
||||
write_mr(MR_TAG, tag_flags);
|
||||
}
|
||||
|
||||
/* Servers:
|
||||
* Sets the message register for returning errors back to client task.
|
||||
* These are usually posix error codes.
|
||||
*/
|
||||
static inline void l4_set_retval(int retval)
|
||||
{
|
||||
write_mr(MR_RETURN, retval);
|
||||
}
|
||||
|
||||
/* Clients:
|
||||
* Learn result of request.
|
||||
*/
|
||||
static inline int l4_get_retval(void)
|
||||
{
|
||||
return read_mr(MR_RETURN);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we're about to do another ipc, this saves the last ipc's
|
||||
* parameters such as the sender and tag information.
|
||||
@@ -195,6 +212,39 @@ static inline int l4_receive_extended(l4id_t from, unsigned int size, void *buf)
|
||||
return l4_ipc(L4_NILTHREAD, from, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return result value as extended IPC.
|
||||
*
|
||||
* Extended IPC copies up to 2KB user address space buffers.
|
||||
* Along with such an ipc, a return value is sent using a primary
|
||||
* mr that is used as the return register.
|
||||
*
|
||||
* It may not be desirable to return a payload on certain conditions,
|
||||
* (such as an error return value) So a nopayload field is provided.
|
||||
*/
|
||||
static inline int l4_return_extended(int retval, unsigned int size,
|
||||
void *buf, int nopayload)
|
||||
{
|
||||
unsigned int flags = 0;
|
||||
l4id_t sender = l4_get_sender();
|
||||
|
||||
l4_set_retval(retval);
|
||||
|
||||
/* Set up flags word for extended ipc */
|
||||
flags = l4_set_ipc_flags(flags, L4_IPC_FLAGS_EXTENDED);
|
||||
flags = l4_set_ipc_msg_index(flags, L4SYS_ARG0);
|
||||
|
||||
/* Write buffer pointer to MR index that we specified */
|
||||
write_mr(L4SYS_ARG0, (unsigned long)buf);
|
||||
|
||||
if (nopayload)
|
||||
flags = l4_set_ipc_size(flags, 0);
|
||||
else
|
||||
flags = l4_set_ipc_size(flags, size);
|
||||
|
||||
return l4_ipc(sender, L4_NILTHREAD, flags);
|
||||
}
|
||||
|
||||
static inline int l4_sendrecv_extended(l4id_t to, l4id_t from,
|
||||
unsigned int tag, void *buf)
|
||||
{
|
||||
@@ -226,23 +276,6 @@ static inline int l4_receive(l4id_t from)
|
||||
return l4_ipc(L4_NILTHREAD, from, 0);
|
||||
}
|
||||
|
||||
/* Servers:
|
||||
* Sets the message register for returning errors back to client task.
|
||||
* These are usually posix error codes.
|
||||
*/
|
||||
static inline void l4_set_retval(int retval)
|
||||
{
|
||||
write_mr(MR_RETURN, retval);
|
||||
}
|
||||
|
||||
/* Clients:
|
||||
* Learn result of request.
|
||||
*/
|
||||
static inline int l4_get_retval(void)
|
||||
{
|
||||
return read_mr(MR_RETURN);
|
||||
}
|
||||
|
||||
static inline void l4_print_mrs()
|
||||
{
|
||||
printf("Message registers: 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n",
|
||||
@@ -259,7 +292,7 @@ static inline int l4_ipc_return(int retval)
|
||||
|
||||
l4_set_retval(retval);
|
||||
|
||||
/* Setting the tag may overwrite retval so we l4_send without tagging */
|
||||
/* Setting the tag would overwrite retval so we l4_send without tagging */
|
||||
return l4_ipc(sender, L4_NILTHREAD, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -24,8 +24,6 @@ static inline int l4_chdir(const char *pathname)
|
||||
|
||||
utcb_full_strcpy_from(pathname);
|
||||
|
||||
write_mr(L4SYS_ARG0, (unsigned long)utcb_full_buffer());
|
||||
|
||||
/* Call pager with shmget() request. Check ipc error. */
|
||||
if ((fd = l4_sendrecv_full(VFS_TID, VFS_TID, L4_IPC_TAG_CHDIR)) < 0) {
|
||||
print_err("%s: L4 IPC Error: %d.\n", __FUNCTION__, fd);
|
||||
|
||||
@@ -26,8 +26,7 @@ static inline int l4_mkdir(const char *pathname, mode_t mode)
|
||||
|
||||
// write_mr(L4SYS_ARG0, (unsigned long)pathname);
|
||||
utcb_full_strcpy_from(pathname);
|
||||
write_mr(L4SYS_ARG0, (unsigned long)utcb_full_buffer());
|
||||
write_mr(L4SYS_ARG1, (u32)mode);
|
||||
write_mr(L4SYS_ARG0, (u32)mode);
|
||||
|
||||
/* Call pager with shmget() request. Check ipc error. */
|
||||
if ((fd = l4_sendrecv_full(PAGER_TID, PAGER_TID, L4_IPC_TAG_MKDIR)) < 0) {
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#include <l4lib/os/posix/readdir.h>
|
||||
#include <l4/macros.h>
|
||||
#include INC_GLUE(memory.h)
|
||||
#include <shpage.h>
|
||||
#include INC_GLUE(message.h)
|
||||
#include <libposix.h>
|
||||
|
||||
/*
|
||||
@@ -29,6 +29,37 @@
|
||||
* Or do it just like read()
|
||||
*/
|
||||
static inline int l4_readdir(int fd, void *buf, size_t count)
|
||||
{
|
||||
int cnt, err;
|
||||
|
||||
write_mr(L4SYS_ARG0, fd);
|
||||
write_mr(L4SYS_ARG1, count);
|
||||
|
||||
/* Call pager with readdir() request. Check ipc error. */
|
||||
if ((err = l4_send(PAGER_TID, L4_IPC_TAG_READDIR)) < 0) {
|
||||
print_err("%s: L4 IPC Error: %d.\n", __FUNCTION__, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Call pager with readdir() request. Check ipc error. */
|
||||
if ((err = l4_receive_extended(PAGER_TID,
|
||||
L4_IPC_EXTENDED_MAX_SIZE,
|
||||
buf)) < 0) {
|
||||
print_err("%s: L4 Extended IPC error: %d.\n", __FUNCTION__, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Check if syscall itself was successful */
|
||||
if ((cnt = l4_get_retval()) < 0) {
|
||||
print_err("%s: READDIR Error: %d.\n", __FUNCTION__, (int)cnt);
|
||||
return cnt;
|
||||
}
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static inline int l4_readdir(int fd, void *buf, size_t count)
|
||||
{
|
||||
int cnt;
|
||||
|
||||
@@ -50,7 +81,7 @@ static inline int l4_readdir(int fd, void *buf, size_t count)
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
#endif
|
||||
static inline int l4_read(int fd, void *buf, size_t count)
|
||||
{
|
||||
int cnt;
|
||||
|
||||
@@ -38,7 +38,7 @@ void sys_exit(struct tcb *task, int status);
|
||||
|
||||
/* Posix calls */
|
||||
int sys_open(struct tcb *sender, const char *pathname, int flags, u32 mode);
|
||||
int sys_readdir(struct tcb *sender, int fd, void *buf, int count);
|
||||
int sys_readdir(struct tcb *sender, int fd, int count, char *dirbuf);
|
||||
int sys_mkdir(struct tcb *sender, const char *pathname, unsigned int mode);
|
||||
int sys_chdir(struct tcb *sender, const char *pathname);
|
||||
|
||||
|
||||
@@ -148,26 +148,32 @@ void handle_requests(void)
|
||||
ret = sys_execve(sender, (char *)mr[0],
|
||||
(char **)mr[1], (char **)mr[2]);
|
||||
if (ret < 0)
|
||||
break; /* We origy for errors */
|
||||
break; /* We reply for errors */
|
||||
else
|
||||
return; /* else we're done */
|
||||
}
|
||||
|
||||
/* FIXME: Fix all these syscalls to read any buffer data from the caller task's utcb. */
|
||||
/*
|
||||
* FIXME: Fix all these syscalls to read any
|
||||
* buffer data from the caller task's utcb.
|
||||
*/
|
||||
|
||||
/* FS0 System calls */
|
||||
case L4_IPC_TAG_OPEN:
|
||||
ret = sys_open(sender, utcb_full_buffer(), (int)mr[0], (unsigned int)mr[1]);
|
||||
break;
|
||||
case L4_IPC_TAG_MKDIR:
|
||||
ret = sys_mkdir(sender, (const char *)mr[0], (unsigned int)mr[1]);
|
||||
ret = sys_mkdir(sender, utcb_full_buffer(), (unsigned int)mr[0]);
|
||||
break;
|
||||
case L4_IPC_TAG_CHDIR:
|
||||
ret = sys_chdir(sender, (const char *)mr[0]);
|
||||
ret = sys_chdir(sender, utcb_full_buffer());
|
||||
break;
|
||||
case L4_IPC_TAG_READDIR:
|
||||
ret = sys_readdir(sender, (int)mr[0], (void *)mr[1], (int)mr[2]);
|
||||
break;
|
||||
|
||||
case L4_IPC_TAG_READDIR: {
|
||||
char dirbuf[L4_IPC_EXTENDED_MAX_SIZE];
|
||||
ret = sys_readdir(sender, (int)mr[0], (int)mr[1], dirbuf);
|
||||
l4_return_extended(ret, L4_IPC_EXTENDED_MAX_SIZE, dirbuf, ret < 0);
|
||||
return;
|
||||
}
|
||||
default:
|
||||
printf("%s: Unrecognised ipc tag (%d) "
|
||||
"received from (%d). Full mr reading: "
|
||||
|
||||
@@ -31,6 +31,8 @@
|
||||
#include <path.h>
|
||||
#include <syscalls.h>
|
||||
|
||||
#include INC_GLUE(message.h)
|
||||
|
||||
/* Copy from one page's buffer into another page */
|
||||
int page_copy(struct page *dst, struct page *src,
|
||||
unsigned long dst_offset, unsigned long src_offset,
|
||||
@@ -1173,17 +1175,22 @@ int fill_dirent(void *buf, unsigned long vnum, int offset, char *name)
|
||||
*
|
||||
* FIXME: Ensure buf is in shared utcb, and count does not exceed it.
|
||||
*/
|
||||
int sys_readdir(struct tcb *t, int fd, void *buf, int count)
|
||||
int sys_readdir(struct tcb *t, int fd, int count, char *dirbuf)
|
||||
{
|
||||
int dirent_size = sizeof(struct dirent);
|
||||
int total = 0, nbytes = 0;
|
||||
unsigned long vnum;
|
||||
struct vnode *v;
|
||||
struct dentry *d;
|
||||
char *buf = dirbuf;
|
||||
|
||||
// printf("%s/%s\n", __TASKNAME__, __FUNCTION__);
|
||||
|
||||
BUG(); /* Do this by extended ipc !!! */
|
||||
/*
|
||||
* FIXME:
|
||||
* Add dirbuf overflow checking
|
||||
*/
|
||||
|
||||
/* Check address is in task's utcb */
|
||||
|
||||
if (fd < 0 || fd > TASK_FILES_MAX || !t->files->fd[fd].vnum)
|
||||
|
||||
@@ -85,7 +85,7 @@
|
||||
#define L4_IPC_EXTENDED_MAX_SIZE (SZ_1K*2)
|
||||
|
||||
/* Primaries aren't used for memcopy. Those ops use this as a parameter */
|
||||
#define L4_UTCB_FULL_BUFFER_SIZE (MR_REST * sizeof(int))
|
||||
#define L4_UTCB_FULL_BUFFER_SIZE (MR_REST * sizeof(int))
|
||||
|
||||
#include INC_GLUE(memlayout.h)
|
||||
|
||||
|
||||
@@ -131,6 +131,8 @@ int ipc_msg_copy(struct ktcb *to, struct ktcb *from)
|
||||
break;
|
||||
case IPC_FLAGS_EXTENDED:
|
||||
if (send_ipc_type == IPC_FLAGS_EXTENDED)
|
||||
/* We do a short copy as well. */
|
||||
ret = ipc_short_copy(to, from);
|
||||
ret = ipc_extended_copy(to, from);
|
||||
if (send_ipc_type == IPC_FLAGS_SHORT)
|
||||
ret = -ENOIPC;
|
||||
|
||||
Reference in New Issue
Block a user