#include <kernel/kernel.h>
#include <kernel/ramdisk.h>
#include <kernel/thread.h>
#include <kernel/proc.h>
#include <kernel/vmm.h>
#include <kernel/memory.h>
#include <kernel/fs.h>
#include <stdlib.h>
#include <wchar.h>
#include <errno.h>
#include <string.h>
extern process_t proc_idle;
ramdisk_t* ramdisk_header;
ramfile_t* ramdisk_files;
typedef struct ramfd_t ramfd_t;
struct ramfd_t
{
file_t file;
ramfile_t *ram;
};
void dump(void* buf, size_t size)
{
unsigned i, j;
char c;
for (i = 0; i < size; i += 16)
{
for (j = 0; j < 16 && i + j < size; j++)
wprintf(L"%02x\t", ((byte*) buf)[i + j]);
for (j = 0; j < 16 && i + j < size; j++)
{
if (((byte*) buf)[i + j] < 0x20)
c = '.';
else
c = ((byte*) buf)[i + j];
wprintf(L"%c", c);
}
//_cputws(L"\n");
}
}
bool ramFsRequest(device_t* dev, request_t* req)
{
ramfd_t *fd;
ramfile_t *file;
unsigned i;
wchar_t name[16];
byte *ptr;
switch (req->code)
{
case FS_OPEN:
assert(req->params.fs_open.name[0] == '/');
//wprintf(L"ramFsRequest: open %s: ", req->params.fs_open.name + 1);
file = NULL;
for (i = 0; i < ramdisk_header->num_files; i++)
{
mbstowcs(name, ramdisk_files[i].name, countof(name));
if (wcsicmp(name, req->params.fs_open.name + 1) == 0)
{
file = ramdisk_files + i;
break;
}
}
if (file == NULL)
{
req->result = ENOTFOUND;
req->params.fs_open.fd = NULL;
wprintf(L"not found\n");
return false;
}
fd = hndAlloc(sizeof(ramfd_t), NULL);
assert(fd != NULL);
fd->file.fsd = dev;
fd->file.pos = 0;
fd->ram = file;
/*wprintf(L"ramFsRequest: FS_OPEN(%s), file = %p = %x, %d bytes\n",
name,
file,
*(dword*) ((byte*) ramdisk_header + fd->ram->offset),
fd->ram->length);*/
req->params.fs_open.fd = &fd->file;
hndSignal(req->event, true);
return true;
case FS_CLOSE:
fd = (ramfd_t*) req->params.fs_close.fd;
assert(fd != NULL);
hndFree(fd);
hndSignal(req->event, true);
return true;
case FS_READ:
fd = (ramfd_t*) req->params.fs_read.fd;
assert(fd != NULL);
if (fd->file.pos + req->params.fs_read.length >= fd->ram->length)
req->params.fs_read.length = fd->ram->length - fd->file.pos;
ptr = (byte*) ramdisk_header + fd->ram->offset + (dword) fd->file.pos;
/*wprintf(L"ramRequest: read %x (%S) at %x => %x = %08x\n",
fd->ram->offset,
fd->ram->name,
(dword) fd->file.pos,
(addr_t) ptr,
*(dword*) ptr);*/
memcpy((void*) req->params.fs_read.buffer,
ptr,
req->params.fs_read.length);
fd->file.pos += req->params.fs_read.length;
hndSignal(req->event, true);
return true;
}
req->result = ENOTIMPL;
return false;
}
device_t* ramMountFs(driver_t* driver, const wchar_t* path, device_t* dev)
{
device_t *ram = hndAlloc(sizeof(device_t), NULL);
ram->driver = driver;
ram->request = ramFsRequest;
return ram;
}
bool ramPageFault(addr_t virt)
{
addr_t phys;
//vm_area_t *area;
if ((virt >= 0xd0000000) && (virt < 0xe0000000))
{
virt &= -PAGE_SIZE;
/*if (vmmMap(&proc_idle, 1, virt,
_sysinfo.ramdisk_phys + virt - 0xd0000000,
0 | MEM_READ | MEM_COMMIT) == NULL)
return false;
else
return true;*/
return memMap(proc_idle.page_dir, virt,
_sysinfo.ramdisk_phys + virt - 0xd0000000,
1, 0 | PRIV_RD | PRIV_PRES);
}
else if (virt >= 0xc0000000)
{
/*area = vmmArea(&proc_idle, (const void*) virt);
if (area == NULL)
return false;
else
{
vmmShare(&proc_idle,
}*/
phys = memTranslate(proc_idle.page_dir, (void*) virt);
if (phys)
{
wprintf(L"Mapping kernel page %x => %x\n", virt, phys);
memMap(current->process->page_dir, virt, phys & -PAGE_SIZE, 1, phys & (PAGE_SIZE - 1));
return true;
}
}
return false;
}
//! Initialises the ramdisk during kernel startup.
/*!
* This routine is called by main() to check the ramdisk (loaded by the
* second-stage boot routine) and map it into the kernel's address
* space. Because it is mapped into the kernel's address space,
* it will be mapped into subsequent address spaces as needed.
*
* \note All objects in the ramdisk (including the ramdisk header, file
* headers and the file data themselves) should be aligned on page
* boundaries. This is done automatically by the \p ramdisk program.
*
* \return A pointer to an IPager interface which will map ramdisk pages
* as needed.
*/
bool INIT_CODE ramInit()
{
ramdisk_header = (ramdisk_t*) 0xd0000000;
ramdisk_files = (ramfile_t*) (ramdisk_header + 1);
if (ramdisk_header->signature != RAMDISK_SIGNATURE_1 &&
ramdisk_header->signature != RAMDISK_SIGNATURE_2)
{
wprintf(L"ramdisk: invalid signature\n");
return false;
}
return true;
}
//! Retrieves a pointer to a file in the ramdisk.
/*!
* This function should only be used to access files before device drivers
* (and, hence, the ramdisk driver) are started.
*
* \param name The name of the file to open. File names in the ramdisk are
* limited to 16 ASCII bytes.
* \return A pointer to the start of the file data.
*/
void* ramOpen(const wchar_t* name)
{
wchar_t temp[16];
int i;
assert(ramdisk_header != NULL);
assert(ramdisk_files != NULL);
for (i = 0; i < ramdisk_header->num_files; i++)
{
mbstowcs(temp, ramdisk_files[i].name, countof(ramdisk_files[i].name));
//wprintf(L"%s\t%x\n", temp, files[i].offset);
if (wcsicmp(name, temp) == 0)
{
assert(ramdisk_files[i].offset < _sysinfo.ramdisk_size);
return (byte*) ramdisk_header + ramdisk_files[i].offset;
}
}
return NULL;
}
size_t ramFileLength(const wchar_t* name)
{
wchar_t temp[16];
int i;
assert(ramdisk_header != NULL);
assert(ramdisk_files != NULL);
for (i = 0; i < ramdisk_header->num_files; i++)
{
mbstowcs(temp, ramdisk_files[i].name, countof(ramdisk_files[i].name));
//wprintf(L"%s\t%x\n", temp, files[i].offset);
if (wcsicmp(name, temp) == 0)
return ramdisk_files[i].length;
}
return -1;
}