Tiberiu Chibici
e3b3584734
==================================================== Mainly changed: Tasking + Implemented multitasking
206 lines
5.8 KiB
C
206 lines
5.8 KiB
C
/*
|
|
* initrd.c
|
|
*
|
|
* Created on: Sep 1, 2011
|
|
* Author: Tiberiu
|
|
*/
|
|
|
|
#define LUXMAGIC 0xCC23AA90
|
|
#define OEMSTR "luxram"
|
|
|
|
#include <fileio.h>
|
|
#include <stdlib.h>
|
|
#include <multiboot.h>
|
|
#include <memory.h>
|
|
#include <debugio.h>
|
|
#include "initrd.h"
|
|
|
|
|
|
/**************************************
|
|
* DEVICE 'FAKE' READ ROUTINE *
|
|
**************************************/
|
|
uint32 luxInitrdDevRead (uint32 UNUSED(offset), void* UNUSED(buffer))
|
|
{
|
|
return LUXMAGIC;
|
|
}
|
|
|
|
|
|
/**************************************
|
|
* OTHER USEFUL ROUTINES *
|
|
**************************************/
|
|
// Navigates and returns the directory entry that contains the file/folder
|
|
luxDirectoryEntry rootDirectoryEntry;
|
|
luxDirectoryEntry* luxGetFile (string path, uint32 data)
|
|
{
|
|
luxHeader* head = (luxHeader*)data;
|
|
uint32 end = strlen(path);
|
|
uint32 start, next = 0;
|
|
char* tmp;
|
|
|
|
// Remove ending '/' (if any)
|
|
if (path[end-1] == '/') --end;
|
|
|
|
// Empty string? Return the root
|
|
if (end == 0) {
|
|
rootDirectoryEntry.De.Flags = 0xB68; // read & execute only
|
|
rootDirectoryEntry.De.GroupId = 0; // system group
|
|
rootDirectoryEntry.De.OwnerId = 0; // system owner
|
|
rootDirectoryEntry.De.Size = sizeof(uint32) + head->RootSize * sizeof(luxDirectoryEntry);
|
|
rootDirectoryEntry.Offset = (uint32)(&head->RootSize) - data; // calculate offset
|
|
|
|
return &rootDirectoryEntry;
|
|
}
|
|
|
|
// Make sure path is correct
|
|
if (path[0] != '/') return NULL;
|
|
|
|
// Parse each directory until we find the one containing the file;
|
|
uint32 cDir = (uint32)&head->RootSize;
|
|
while (next < end)
|
|
{
|
|
// Parse string
|
|
start = next + 1; // Skip path separator
|
|
tmp = strchr(&path[start], '/'); // Find next separator
|
|
next = (!tmp) ? end : (uint32)(tmp - path) ; // Mark end of string, or next dir position in path
|
|
|
|
// strchr doesn't know when to end
|
|
if (next >= end) { tmp = 0; next = end; }
|
|
|
|
// Look for directory
|
|
uint32 i, find = 0xffffffff;
|
|
uint32 size = *(uint32*)cDir;
|
|
luxDirectoryEntry* de = (luxDirectoryEntry*) (cDir + sizeof(uint32));
|
|
for (i = 0; i < size && find == 0xffffffff; i++)
|
|
if (strncmp(de[i].De.Name, &path[start], strlen(de[i].De.Name)) == 0)
|
|
find = i;
|
|
|
|
// Not found? Nope, not good
|
|
if (find == 0xffffffff) return NULL;
|
|
|
|
// End of string? Return directory entry
|
|
if (!tmp) return &de[find];
|
|
|
|
// make sure we don't try to read a file as a folder
|
|
if ((de[find].De.Flags & 0x7) != FileDirectory) return NULL;
|
|
// Not end of string? Continue
|
|
cDir = (uint32) (data + de[find].Offset);
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/**************************************
|
|
* FILE SYSTEM INTERFACE ROUTINES *
|
|
**************************************/
|
|
uint32 luxDetect (MountPoint* mp)
|
|
{
|
|
void* buffer = kmalloc(mp->BlockSize); // must allocate a buffer for non-initrd devices...
|
|
uint32 result = mp->Read(0, buffer); // read something
|
|
kfree(buffer); // get rid of the not needed buffer
|
|
|
|
return (result == LUXMAGIC); // returned magic number? good
|
|
}
|
|
|
|
// Test if a file exists
|
|
DirectoryEntry* luxTest (MountPoint* mp, string path)
|
|
{
|
|
// MountPoint.FsData[0] contains initrd image start address
|
|
// luxDirectoryEntry contains a DirectoryEntry
|
|
return (DirectoryEntry*) luxGetFile(path, mp->FsData[0]); // Get a directory and see
|
|
}
|
|
|
|
// Open a file
|
|
FILE* luxOpen (MountPoint* mp, FILE* f, string path)
|
|
{
|
|
// Find it first. mp->FsData[0] contains initrd image start address.
|
|
luxDirectoryEntry* entry = luxGetFile(path, mp->FsData[0]);
|
|
|
|
// Invalid entry
|
|
if (entry == NULL) return NULL;
|
|
|
|
// Set some data fields
|
|
f->Name = entry->De.Name;
|
|
f->Flags = entry->De.Flags;
|
|
f->GroupId = entry->De.GroupId;
|
|
f->OwnerId = entry->De.OwnerId;
|
|
f->Size = entry->De.Size;
|
|
|
|
// Set up the buffer info. We will use these to read/write the file.
|
|
f->BufStart = (void*) (mp->FsData[0] + entry->Offset);
|
|
f->BufPos = f->BufStart;
|
|
f->BufEnd = f->BufStart + entry->De.Size;
|
|
|
|
// And return it
|
|
return f;
|
|
}
|
|
|
|
// Close a file
|
|
FILE* luxClose (MountPoint* UNUSED(mp), FILE* f)
|
|
{
|
|
// Just empty buffer info, so we don't attempt to read it again
|
|
f->BufStart = f->BufPos = f->BufEnd = NULL;
|
|
return f;
|
|
}
|
|
|
|
// Read data from a file
|
|
// Returns byte count read
|
|
uint32 luxRead (MountPoint* UNUSED(mp), FILE* f, uint32 elemsz, uint32 n, uint8* buffer)
|
|
{
|
|
// Make sure we don't read more than we can
|
|
uint32 total = Min(elemsz * n, (uint32)f->BufEnd - (uint32)f->BufPos);
|
|
|
|
memcpy(buffer, f->BufPos, total); // Copy data
|
|
f->BufPos = (void*) ((uint32)f->BufPos + total); // Set new buffer position
|
|
return total; // Return byte count read
|
|
}
|
|
|
|
// Read contents of a directory
|
|
DirectoryEntry* luxReadDir (MountPoint* UNUSED(mp), FILE* f, uint32 index)
|
|
{
|
|
uint32 size = *(uint32*)f->BufStart;
|
|
luxDirectoryEntry* de = (luxDirectoryEntry*) ((uint32)f->BufStart + sizeof(uint32));
|
|
|
|
if (index >= size) return NULL;
|
|
return (DirectoryEntry*) &de[index];
|
|
}
|
|
|
|
|
|
/**************************************
|
|
* INITIALIZATION ROUTINE *
|
|
**************************************/
|
|
void luxInitrdInstall (MultibootInfo* info)
|
|
{
|
|
uint32 i;
|
|
MountPoint* mp;
|
|
|
|
// Register file system
|
|
FileSystem fs = {0, "luxinitrd", luxDetect, 0, 0,
|
|
luxOpen, luxClose, luxRead, 0, luxTest, luxReadDir};
|
|
VfsInstallFs(&fs);
|
|
|
|
// Check for multiboot info flags to see if any modules are loaded
|
|
if ((info->Flags & 8) == 0) {
|
|
Error("Initrd", "No boot modules found!");
|
|
return;
|
|
}
|
|
|
|
// Loop through each module and if it is an initrd image, mount it
|
|
MultibootModule* modules = (MultibootModule*) info->ModulesAddress;
|
|
|
|
for (i = 0; i < info->ModulesCount; i++)
|
|
if (*((uint32*) modules[i].ModuleStart) == LUXMAGIC)
|
|
{
|
|
// Mount the device
|
|
Log("Initrd", "Found initrd image at 0x%x.\n", modules[i].ModuleStart);
|
|
mp = VfsMount("initrd", luxInitrdDevRead, NULL, 0x0);
|
|
|
|
// Set up data fields
|
|
mp->FsData[0] = modules[i].ModuleStart;
|
|
mp->FsData[1] = modules[i].ModuleEnd;
|
|
}
|
|
else {
|
|
Log("Initrd", "Found module @ 0x%x, but not initrd image.\n", modules[i].ModuleStart);
|
|
}
|
|
}
|