/* * initrd.c * * Created on: Sep 1, 2011 * Author: Tiberiu */ #define LUXMAGIC 0xCC23AA90 #define OEMSTR "luxram" #include #include #include #include #include #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]; }