203 lines
4.8 KiB
C
203 lines
4.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"
|
|
|
|
|
|
luxDEVICE *luxDevices;
|
|
uint32 luxDeviceCount;
|
|
|
|
luxFILE *luxFiles;
|
|
uint32 luxFileCount;
|
|
uint32 luxFilesAllocated;
|
|
|
|
|
|
/**************************************
|
|
* DEVICE 'FAKE' READ ROUTINE *
|
|
**************************************/
|
|
uint32 luxDevRead (uint32 UNUSED(offset), void* UNUSED(buffer))
|
|
{
|
|
return LUXMAGIC;
|
|
}
|
|
|
|
/**************************************
|
|
* INITIALIZATION ROUTINE *
|
|
**************************************/
|
|
void luxInitrdInstall (MultibootInfo* info)
|
|
{
|
|
// Install filesystem
|
|
FileSystem fs = {0, "luxinitrd", luxDetect, 0, 0,
|
|
luxOpen, luxClose, luxRead, 0, luxTest, luxReadDir};
|
|
|
|
VfsInstallFs(&fs);
|
|
|
|
|
|
// See what modules are loaded in the multiboot info
|
|
if ((info->Flags & 8) == 0 || info->ModulesCount == 0) return; // nothing was loaded
|
|
|
|
uint32 i;
|
|
MultibootModule* modules = (MultibootModule*) info->ModulesAddress;
|
|
luxDevices = kmalloc(sizeof(luxDEVICE) * info->ModulesCount);
|
|
luxDeviceCount = 0;
|
|
|
|
for (i = 0; i < info->ModulesCount; i++) {
|
|
|
|
// Check magic number, to make sure module is a initrd image
|
|
luxHeader* head = (luxHeader*) modules[i].ModuleStart;
|
|
if (head->Magic != LUXMAGIC) {
|
|
Log("Initrd", "Magic = 0x%x [bad] ModuleStart = 0x%x\n", head->Magic, modules[i].ModuleStart);
|
|
continue;
|
|
}
|
|
|
|
// Set up entry
|
|
luxDevices[luxDeviceCount].Data = (void*) modules[i].ModuleStart;
|
|
luxDevices[luxDeviceCount].Size = modules[i].ModuleEnd - modules[i].ModuleStart;
|
|
|
|
// Register virtual device. Instead of blocksize, we give the dev no, so we can identify it later
|
|
VfsMount("initrd", luxDevRead, 0, luxDeviceCount);
|
|
++luxDeviceCount;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/**************************************
|
|
* OTHER USEFUL ROUTINES *
|
|
**************************************/
|
|
uint32 luxGetFileSlot()
|
|
{
|
|
// Find an empty slot
|
|
uint32 i = 0;
|
|
for (i = 0; i < luxFileCount; i++)
|
|
if (luxFiles[i].Id == 0xffffffff) return i;
|
|
|
|
// Nothing found? Allocate more slots if necessary
|
|
if (luxFileCount >= luxFilesAllocated)
|
|
{
|
|
luxFilesAllocated += 4;
|
|
luxFiles = kmrealloc(luxFiles, luxFilesAllocated);
|
|
}
|
|
|
|
// Give last slot
|
|
++luxFileCount;
|
|
return (luxFileCount-1);
|
|
}
|
|
|
|
// Navigates and returns the directory entry that contains the file/folder
|
|
luxDirectoryEntry* luxGetFile (string path, uint32 dev)
|
|
{
|
|
luxHeader* root = (luxHeader*) luxDevices[dev].Data;
|
|
luxDirectory* current = root->Root;
|
|
luxDirectoryEntry rt = {"root", 0xB68, 0, 0, 0, {0,0}, {0,0}, {0,0}, (uint32)&root->Root};
|
|
|
|
if (path[0] != '\\')
|
|
return &rt;
|
|
|
|
path = path + 1;
|
|
|
|
|
|
while (path)
|
|
{
|
|
// Trim the next path separator
|
|
string tmp = strchr(path, '\\');
|
|
if (tmp) {
|
|
*tmp = 0; tmp = tmp + 1;
|
|
if (!*tmp) tmp = 0;
|
|
}
|
|
|
|
// Find the folder/file in current directory
|
|
uint32 i, found = 0xffffffff;
|
|
for (i = 0; i < current->Count && found == 0xffffffff; i++)
|
|
if (strcmp(path, current->Entries[i].Name) == 0) found = i;
|
|
|
|
// Check if the file/folder was found
|
|
if (found == 0xffffffff) return NULL;
|
|
|
|
// Return entry pointer if done
|
|
if (!tmp) return ¤t->Entries[found];
|
|
|
|
// Go inside
|
|
current = (luxDirectory*) (current->Entries[found].Offset + (uint32)root);
|
|
path = tmp;
|
|
}
|
|
|
|
// We shouldn't get here
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/**************************************
|
|
* FILE SYSTEM INTERFACE ROUTINES *
|
|
**************************************/
|
|
uint32 luxDetect (DevReadRoutine rd, uint32 blocksz)
|
|
{
|
|
// Check magic result, which is returned by our device read function
|
|
void* buffer = kmalloc(blocksz);
|
|
uint32 result = (*rd)(0, buffer);
|
|
kfree(buffer);
|
|
|
|
return (result == LUXMAGIC);
|
|
}
|
|
|
|
// Returns element count read
|
|
uint32 luxRead (const MountPoint* UNUSED(mp), FILE* f, uint32 elemsz, uint32 n, uint8* buffer)
|
|
{
|
|
uint32 temp = Min(n*elemsz, luxFiles[f->Id].Size);
|
|
|
|
memcpy(buffer, luxFiles[f->Id].Pos, temp);
|
|
luxFiles[f->Id].Size -= temp;
|
|
|
|
return temp;
|
|
}
|
|
|
|
FILE* luxOpen (const MountPoint* mp, FILE* f, string path)
|
|
{
|
|
f->Id = luxGetFileSlot();
|
|
luxDirectoryEntry* entry = luxGetFile(path, mp->BlockSize);
|
|
|
|
f->Name = entry->Name;
|
|
f->Flags = entry->Flags;
|
|
f->GroupId = entry->GroupId;
|
|
f->OwnerId = entry->OwnerId;
|
|
f->Size = entry->Size;
|
|
|
|
luxFiles[f->Id].Id = f->Id;
|
|
luxFiles[f->Id].Pos = luxFiles[f->Id].Start = entry->Offset + luxDevices[mp->BlockSize].Data;
|
|
luxFiles[f->Id].Size = entry->Size;
|
|
|
|
return f;
|
|
}
|
|
|
|
DirectoryEntry* luxTest (const MountPoint* mp, string path)
|
|
{
|
|
return (DirectoryEntry*) luxGetFile(path, mp->BlockSize);
|
|
}
|
|
|
|
FILE* luxClose (const MountPoint* UNUSED(mp), FILE* f)
|
|
{
|
|
luxFiles[f->Id].Id = NULL;
|
|
|
|
return f;
|
|
}
|
|
|
|
DirectoryEntry* luxReadDir (const MountPoint* UNUSED(mp), FILE* f, uint32 index)
|
|
{
|
|
luxDirectory* dir = luxFiles[f->Id].Start;
|
|
|
|
if (index > dir->Count) return NULL;
|
|
return (DirectoryEntry*) &dir->Entries[index];
|
|
}
|
|
|