haeberlen@ira.uka.de
#include <config.h>
#include <new>
#include <stdio.h>
#include <string.h>
#include <l4/schedule.h>
#include <sdi/panic.h>
#include <sdi/log.h>
#include <sdi/locator.h>
#include "root.h"
#include <idl4glue.h>
#include <if/ifblockdev.h>
#include <if/iflocator.h>
#include "ramdisk-server.h"
#define SHOW_ERRORS
namespace {
const size_t BLOCKSIZE = 1024;
const size_t MAX_RAMDISKCOUNT = 10;
static char buffer[BLOCKSIZE];
struct Ramdisk
{
void* ptr;
size_t size;
};
Ramdisk ramdisks[MAX_RAMDISKCOUNT];
size_t ramdisk_count = 0;
void announce()
{
for(size_t i = 0; i < ramdisk_count; ++i) {
char name[128];
snprintf(name, sizeof(name), "ramdisk%u", i);
if(Register(GetLocator(), name, IF_BLOCKDEV_ID, i) != OK)
panic("Couldn't register ramdisk");
LogMessage("Ramdisk '%s' registered", name);
}
}
bool is_minixdisk(const L4_BootRec_t* bootrec)
{
const uint16_t MINIXFS_MAGIC = 0x138f;
if(L4_Type (bootrec) != L4_BootInfo_Module)
return false;
if(L4_Module_Size(bootrec) < 2048)
return false;
L4_Word_t addr = L4_Module_Start(bootrec);
char* magic_ptr = reinterpret_cast<char*> (addr) + 1040;
uint16_t magic = * (reinterpret_cast<uint16_t*> (magic_ptr));
if(magic != MINIXFS_MAGIC)
return false;
return true;
}
void detect_ramdisks()
{
const L4_BootInfo_t* bootinfo = get_bootinfo();
const L4_BootRec_t* bootrec = L4_BootInfo_FirstEntry(bootinfo);
for(L4_Word_t i = 0; i < L4_BootInfo_Entries(bootinfo); ++i,
bootrec = L4_BootRec_Next(bootrec)) {
if(!is_minixdisk(bootrec))
continue;
if(ramdisk_count >= MAX_RAMDISKCOUNT) {
printf("Too many ramdisks, skipping module %lu", i);
break;
}
Ramdisk& ramdisk = ramdisks[ramdisk_count];
ramdisk.ptr = reinterpret_cast<void*> (L4_Module_Start(bootrec));
ramdisk.size = static_cast<size_t> (L4_Module_Size(bootrec));
ramdisk_count++;
LogMessage("Module %lu is a ramdisk at %p Len %u\n", i, ramdisk.ptr, ramdisk.size);
}
}
}
IDL4_INLINE void ramdisk_GetBlockSize_implementation(CORBA_Object _caller, const objectid_t devhandle, idlsize_t *blocksize, idl4_server_environment *_env)
{
if(devhandle >= ramdisk_count) {
#ifdef SHOW_ERRORS
printf("Invalid devhandle");
#endif
CORBA_exception_set(_env, ex_no_such_device, 0);
return;
}
*blocksize = BLOCKSIZE;
}
IDL4_PUBLISH_RAMDISK_GETBLOCKSIZE(ramdisk_GetBlockSize_implementation);
IDL4_INLINE void ramdisk_ReadBlock_implementation(CORBA_Object _caller, const objectid_t devhandle, const uint32_t block, buffer_t *buffer, idl4_server_environment *_env)
{
if(devhandle >= ramdisk_count) {
#ifdef SHOW_ERRORS
printf("Invalid devhandle\n");
#endif
buffer->_length = 0;
CORBA_exception_set(_env, ex_no_such_device, 0);
return;
}
Ramdisk* ramdisk = & ramdisks[devhandle];
size_t offset = block * BLOCKSIZE;
if(offset + BLOCKSIZE > ramdisk->size) {
#ifdef SHOW_ERRORS
printf("Invalid block %u\n", block);
#endif
CORBA_exception_set(_env, ex_invalid_parameter, 0);
buffer->_length = 0;
return;
}
#ifdef TRACE_CALLSE
LogMessage("ReadBlock %u", block);
#endif
char* memory = reinterpret_cast<char*> (ramdisk->ptr) + offset;
memcpy(buffer->_buffer, memory, BLOCKSIZE);
buffer->_length = BLOCKSIZE;
}
IDL4_PUBLISH_RAMDISK_READBLOCK(ramdisk_ReadBlock_implementation);
IDL4_INLINE void ramdisk_WriteBlock_implementation(CORBA_Object _caller, const objectid_t devhandle, const uint32_t block, const buffer_t *buffer, idl4_server_environment *_env)
{
if(devhandle >= ramdisk_count) {
#ifdef SHOW_ERRORS
printf("Invalid devhandle\n");
#endif
CORBA_exception_set(_env, ex_no_such_device, 0);
return;
}
Ramdisk* ramdisk = & ramdisks[devhandle];
if(buffer->_length != BLOCKSIZE) {
#ifdef SHOW_ERRORS
printf("Invalid buffersize %d\n", buffer->_length);
#endif
CORBA_exception_set(_env, ex_invalid_parameter, 0);
return;
}
size_t offset = block * BLOCKSIZE;
if(offset + BLOCKSIZE > ramdisk->size) {
#ifdef SHOW_ERRORS
printf("Invalid block %u\n", block);
#endif
CORBA_exception_set(_env, ex_invalid_parameter, 0);
return;
}
#ifdef TRACE_CALLS
LogMessage("WriteBlock %u", block);
#endif
char* memory = reinterpret_cast<char*> (ramdisk->ptr) + offset;
memcpy(memory, buffer->_buffer, BLOCKSIZE);
}
IDL4_PUBLISH_RAMDISK_WRITEBLOCK(ramdisk_WriteBlock_implementation);
void *ramdisk_vtable_3[RAMDISK_DEFAULT_VTABLE_SIZE] = RAMDISK_DEFAULT_VTABLE_3;
void *ramdisk_vtable_discard[RAMDISK_DEFAULT_VTABLE_SIZE] = RAMDISK_DEFAULT_VTABLE_DISCARD;
void **ramdisk_itable[4] = { ramdisk_vtable_discard, ramdisk_vtable_discard, ramdisk_vtable_discard, ramdisk_vtable_3 };
void ramdisk_server()
{
L4_ThreadId_t partner;
L4_MsgTag_t msgtag;
idl4_msgbuf_t msgbuf;
long cnt;
idl4_msgbuf_init(&msgbuf);
idl4_msgbuf_add_buffer(&msgbuf, buffer, BLOCKSIZE);
detect_ramdisks();
announce();
while (1)
{
partner = L4_nilthread;
msgtag.raw = 0;
cnt = 0;
while (1)
{
idl4_msgbuf_sync(&msgbuf);
idl4_reply_and_wait(&partner, &msgtag, &msgbuf, &cnt);
if (idl4_is_error(&msgtag))
break;
idl4_process_request(&partner, &msgtag, &msgbuf, &cnt, ramdisk_itable[idl4_get_interface_id(&msgtag) & RAMDISK_IID_MASK][idl4_get_function_id(&msgtag) & RAMDISK_FID_MASK]);
}
}
}
void ramdisk_discard()
{
panic("message for ramdisk discarded");
}