From 5fc81fa5e050f48374a6aff5636f3e60313dfc78 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Fri, 13 Nov 2009 15:09:46 +0800 Subject: [PATCH] Fixes and Cleanup - Fixed text mode in BochsGA driver and hence set it to the VTerm default - Moved Ext2 Filesystem driver to Modules tree (As FS_Ext2) - Included root Makefile in git tree - Slight changes to the in-process USB code - Updated the README - Inconcequential changes to other files --- Kernel/arch/x86/errors.c | 6 + Kernel/arch/x86/proc.c | 9 +- Kernel/drv/vterm.c | 11 +- Kernel/modules.c | 4 + Kernel/vfs/fs/ext2.c | 744 ------------------ Makefile | 39 + Makefile.cfg | 4 +- Modules/BochsVBE/Makefile | 7 - Modules/BochsVBE/bochsvbe.c | 451 ----------- Modules/FS_Ext2/Makefile | 7 + Modules/FS_Ext2/dir.c | 228 ++++++ Modules/FS_Ext2/ext2.c | 309 ++++++++ Modules/FS_Ext2/ext2_common.h | 46 ++ .../fs/fs_ext2.h => Modules/FS_Ext2/ext2fs.h | 8 +- Modules/FS_Ext2/read.c | 89 +++ Modules/FS_Ext2/write.c | 176 +++++ Modules/USB/uhci.c | 18 +- Modules/USB/usb.h | 62 ++ README | 9 +- Usermode/Libraries/libc.so_src/lib.h | 16 +- Usermode/Libraries/libc.so_src/stub.c | 37 + Usermode/include/acess/devices.h | 3 + Usermode/include/acess/devices/terminal.h | 58 ++ 23 files changed, 1112 insertions(+), 1229 deletions(-) delete mode 100644 Kernel/vfs/fs/ext2.c create mode 100644 Makefile delete mode 100644 Modules/BochsVBE/Makefile delete mode 100644 Modules/BochsVBE/bochsvbe.c create mode 100644 Modules/FS_Ext2/Makefile create mode 100644 Modules/FS_Ext2/dir.c create mode 100644 Modules/FS_Ext2/ext2.c create mode 100644 Modules/FS_Ext2/ext2_common.h rename Kernel/vfs/fs/fs_ext2.h => Modules/FS_Ext2/ext2fs.h (94%) create mode 100644 Modules/FS_Ext2/read.c create mode 100644 Modules/FS_Ext2/write.c create mode 100644 Usermode/include/acess/devices/terminal.h diff --git a/Kernel/arch/x86/errors.c b/Kernel/arch/x86/errors.c index d87b1c62..2f94972c 100644 --- a/Kernel/arch/x86/errors.c +++ b/Kernel/arch/x86/errors.c @@ -17,6 +17,12 @@ extern void Threads_Dump(); void Error_Backtrace(Uint eip, Uint ebp); // === CODE === +void __stack_chk_fail() +{ + Panic("FATAL ERROR: Stack Check Failed\n"); + for(;;); +} + /** * \fn void ErrorHandler(tRegs *Regs) * \brief General Error Handler diff --git a/Kernel/arch/x86/proc.c b/Kernel/arch/x86/proc.c index 5301401e..d7f460fa 100644 --- a/Kernel/arch/x86/proc.c +++ b/Kernel/arch/x86/proc.c @@ -560,10 +560,11 @@ void Proc_Scheduler(int CPU) __asm__ __volatile__ ("mov %0, %%cr3"::"a"(gCurrentThread->MemState.CR3)); // Switch threads __asm__ __volatile__ ( - "mov %1, %%esp\n\t" - "mov %2, %%ebp\n\t" - "jmp *%3" : : + "mov %1, %%esp\n\t" // Restore ESP + "mov %2, %%ebp\n\t" // and EBP + "jmp *%3" : : // And return to where we saved state (Proc_Clone or Proc_Scheduler) "a"(SWITCH_MAGIC), "b"(gCurrentThread->SavedState.ESP), - "d"(gCurrentThread->SavedState.EBP), "c"(gCurrentThread->SavedState.EIP)); + "d"(gCurrentThread->SavedState.EBP), "c"(gCurrentThread->SavedState.EIP) + ); for(;;); // Shouldn't reach here } diff --git a/Kernel/drv/vterm.c b/Kernel/drv/vterm.c index 09f85ff6..87f71ede 100644 --- a/Kernel/drv/vterm.c +++ b/Kernel/drv/vterm.c @@ -16,8 +16,8 @@ #define MAX_INPUT_CHARS32 64 #define MAX_INPUT_CHARS8 (MAX_INPUT_CHARS32*4) #define VT_SCROLLBACK 1 // 2 Screens of text -#define DEFAULT_OUTPUT "VGA" -//#define DEFAULT_OUTPUT "BochsGA" +//#define DEFAULT_OUTPUT "VGA" +#define DEFAULT_OUTPUT "BochsGA" #define DEFAULT_INPUT "PS2Keyboard" #define DEFAULT_WIDTH 80 #define DEFAULT_HEIGHT 25 @@ -197,7 +197,7 @@ int VT_Install(char **Arguments) void VT_InitOutput() { giVT_OutputDevHandle = VFS_Open(gsVT_OutputDevice, VFS_OPENFLAG_WRITE); - LOG("giVT_OutputDevHandle = %x\n", giVT_OutputDevHandle); + Log("giVT_OutputDevHandle = %x\n", giVT_OutputDevHandle); VT_SetTerminal( 0 ); } @@ -896,7 +896,7 @@ void VT_int_ChangeMode(tVTerm *Term, int NewMode) Uint8 *VT_Font_GetChar(Uint32 Codepoint); // === GLOBALS === -int giVT_CharWidth = FONT_WIDTH; +int giVT_CharWidth = FONT_WIDTH+1; int giVT_CharHeight = FONT_HEIGHT; // === CODE === @@ -909,13 +909,14 @@ void VT_Font_Render(Uint32 Codepoint, void *Buffer, int Pitch, Uint32 BGC, Uint3 Uint8 *font; Uint32 *buf = Buffer; int x, y; + font = VT_Font_GetChar(Codepoint); for(y = 0; y < FONT_HEIGHT; y ++) { for(x = 0; x < FONT_WIDTH; x ++) { - if(*font & (1 << (FONT_WIDTH-x))) + if(*font & (1 << (FONT_WIDTH-x-1))) buf[x] = FGC; else buf[x] = BGC; diff --git a/Kernel/modules.c b/Kernel/modules.c index b1d858c7..a4e639b8 100644 --- a/Kernel/modules.c +++ b/Kernel/modules.c @@ -46,6 +46,7 @@ int Modules_LoadBuiltins() if(strcmp(deps[j], gKernelModules[k].Name) == 0) break; } + Log("%s requires %s\n", gKernelModules[i].Name, deps[j]); if(k == giNumBuiltinModules) { Warning("Unable to find dependency '%s' for '%s' in kernel", deps[j], gKernelModules[i].Name); @@ -64,6 +65,8 @@ int Modules_LoadBuiltins() for( i = 0; i < giNumBuiltinModules; i++ ) { if( baIsLoaded[i] ) continue; // Ignore already loaded modules + + deps = gKernelModules[i].Dependencies; if( deps ) { @@ -75,6 +78,7 @@ int Modules_LoadBuiltins() } // `k` is assumed to be less than `giNumBuiltinModules` + Log("baIsLoaded[%i(%s)] = %i\n", k, deps[j], baIsLoaded[k]); // If a dependency failed, skip and mark as failed if( baIsLoaded[k] == -1 ) { baIsLoaded[i] = -1; diff --git a/Kernel/vfs/fs/ext2.c b/Kernel/vfs/fs/ext2.c deleted file mode 100644 index 0b60e542..00000000 --- a/Kernel/vfs/fs/ext2.c +++ /dev/null @@ -1,744 +0,0 @@ -/* - * Acess OS - * Ext2 Driver Version 1 - */ -/** - * \file fs/ext2.c - * \brief Second Extended Filesystem Driver - * \todo Implement file full write support - */ -#define DEBUG 1 -#define VERBOSE 0 -#include -#include -#include -#include "fs_ext2.h" - -#define EXT2_UPDATE_WRITEBACK 1 - -// === STRUCTURES === -typedef struct { - int FD; - int CacheID; - tVFS_Node RootNode; - - tExt2_SuperBlock SuperBlock; - int BlockSize; - - int GroupCount; - tExt2_Group Groups[]; -} tExt2_Disk; - -// === PROTOTYPES === - int Ext2_Install(char **Arguments); -// Interface Functions -tVFS_Node *Ext2_InitDevice(char *Device, char **Options); -void Ext2_Unmount(tVFS_Node *Node); -Uint64 Ext2_Read(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer); -Uint64 Ext2_Write(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer); -void Ext2_CloseFile(tVFS_Node *Node); -char *Ext2_ReadDir(tVFS_Node *Node, int Pos); -tVFS_Node *Ext2_FindDir(tVFS_Node *Node, char *FileName); - int Ext2_MkNod(tVFS_Node *Node, char *Name, Uint Flags); -// Internal Helpers - int Ext2_int_GetInode(tVFS_Node *Node, tExt2_Inode *Inode); -tVFS_Node *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeId, char *Name); - int Ext2_int_ReadInode(tExt2_Disk *Disk, Uint InodeId, tExt2_Inode *Inode); -Uint64 Ext2_int_GetBlockAddr(tExt2_Disk *Disk, Uint32 *Blocks, int BlockNum); -Uint32 Ext2_int_AllocateInode(tExt2_Disk *Disk, Uint32 Parent); -Uint32 Ext2_int_AllocateBlock(tExt2_Disk *Disk, Uint32 PrevBlock); -void Ext2_int_UpdateSuperblock(tExt2_Disk *Disk); - -// === SEMI-GLOBALS === -MODULE_DEFINE(0, 0x5B /*v0.90*/, EXT2, Ext2_Install, NULL); -tExt2_Disk gExt2_disks[6]; - int giExt2_count = 0; -tVFS_Driver gExt2_FSInfo = { - "ext2", 0, Ext2_InitDevice, Ext2_Unmount, NULL - }; - -// === CODE === - -/** - * \fn int Ext2_Install(char **Arguments) - * \brief Install the Ext2 Filesystem Driver - */ -int Ext2_Install(char **Arguments) -{ - VFS_AddDriver( &gExt2_FSInfo ); - return 1; -} - -/** - \fn tVFS_Node *Ext2_InitDevice(char *Device, char **Options) - \brief Initializes a device to be read by by the driver - \param Device String - Device to read from - \param Options NULL Terminated array of option strings - \return Root Node -*/ -tVFS_Node *Ext2_InitDevice(char *Device, char **Options) -{ - tExt2_Disk *disk; - int fd; - int groupCount; - tExt2_SuperBlock sb; - tExt2_Inode inode; - - ENTER("sDevice pOptions", Device, Options); - - // Open Disk - fd = VFS_Open(Device, VFS_OPENFLAG_READ|VFS_OPENFLAG_WRITE); //Open Device - if(fd == -1) { - Warning("[EXT2 ] Unable to open '%s'", Device); - LEAVE('n'); - return NULL; - } - - // Read Superblock at offset 1024 - VFS_ReadAt(fd, 1024, 1024, &sb); // Read Superblock - - // Sanity Check Magic value - if(sb.s_magic != 0xEF53) { - Warning("[EXT2 ] Volume '%s' is not an EXT2 volume", Device); - VFS_Close(fd); - LEAVE('n'); - return NULL; - } - - // Get Group count - groupCount = DivUp(sb.s_blocks_count, sb.s_blocks_per_group); - LOG("groupCount = %i", groupCount); - - // Allocate Disk Information - disk = malloc(sizeof(tExt2_Disk) + sizeof(tExt2_Group)*groupCount); - if(!disk) { - Warning("[EXT2 ] Unable to allocate disk structure"); - VFS_Close(fd); - LEAVE('n'); - return NULL; - } - disk->FD = fd; - memcpy(&disk->SuperBlock, &sb, 1024); - disk->GroupCount = groupCount; - - // Get an inode cache handle - disk->CacheID = Inode_GetHandle(); - - // Get Block Size - LOG("s_log_block_size = 0x%x", sb.s_log_block_size); - disk->BlockSize = 1024 << sb.s_log_block_size; - - // Read Group Information - VFS_ReadAt( - disk->FD, - sb.s_first_data_block * disk->BlockSize + 1024, - sizeof(tExt2_Group)*groupCount, - disk->Groups - ); - - #if VERBOSE - LOG("Block Group 0"); - LOG(".bg_block_bitmap = 0x%x", disk->Groups[0].bg_block_bitmap); - LOG(".bg_inode_bitmap = 0x%x", disk->Groups[0].bg_inode_bitmap); - LOG(".bg_inode_table = 0x%x", disk->Groups[0].bg_inode_table); - LOG("Block Group 1"); - LOG(".bg_block_bitmap = 0x%x", disk->Groups[1].bg_block_bitmap); - LOG(".bg_inode_bitmap = 0x%x", disk->Groups[1].bg_inode_bitmap); - LOG(".bg_inode_table = 0x%x", disk->Groups[1].bg_inode_table); - #endif - - // Get root Inode - Ext2_int_ReadInode(disk, 2, &inode); - - // Create Root Node - memset(&disk->RootNode, 0, sizeof(tVFS_Node)); - disk->RootNode.Inode = 2; // Root inode ID - disk->RootNode.ImplPtr = disk; // Save disk pointer - disk->RootNode.Size = -1; // Fill in later (on readdir) - disk->RootNode.Flags = VFS_FFLAG_DIRECTORY; - - disk->RootNode.ReadDir = Ext2_ReadDir; - disk->RootNode.FindDir = Ext2_FindDir; - //disk->RootNode.Relink = Ext2_Relink; - - // Complete root node - disk->RootNode.UID = inode.i_uid; - disk->RootNode.GID = inode.i_gid; - disk->RootNode.NumACLs = 1; - disk->RootNode.ACLs = &gVFS_ACL_EveryoneRW; - - #if DEBUG - LOG("inode.i_size = 0x%x", inode.i_size); - LOG("inode.i_block[0] = 0x%x", inode.i_block[0]); - #endif - - LEAVE('p', &disk->RootNode); - return &disk->RootNode; -} - -/** - * \fn void Ext2_Unmount(tVFS_Node *Node) - * \brief Close a mounted device - */ -void Ext2_Unmount(tVFS_Node *Node) -{ - tExt2_Disk *disk = Node->ImplPtr; - - VFS_Close( disk->FD ); - Inode_ClearCache( disk->CacheID ); - memset(disk, 0, sizeof(tExt2_Disk)+disk->GroupCount*sizeof(tExt2_Group)); - free(disk); -} - -/** - * \fn Uint64 Ext2_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) - * \brief Read from a file - */ -Uint64 Ext2_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) -{ - tExt2_Disk *disk = Node->ImplPtr; - tExt2_Inode inode; - Uint64 base; - Uint block; - Uint64 remLen; - - ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer); - - // Get Inode - Ext2_int_GetInode(Node, &inode); - - // Sanity Checks - if(Offset >= inode.i_size) { - LEAVE('i', 0); - return 0; - } - if(Offset + Length > inode.i_size) - Length = inode.i_size - Offset; - - block = Offset / disk->BlockSize; - Offset = Offset / disk->BlockSize; - base = Ext2_int_GetBlockAddr(disk, inode.i_block, block); - if(base == 0) { - Warning("[EXT2 ] NULL Block Detected in INode 0x%llx", Node->Inode); - LEAVE('i', 0); - return 0; - } - - // Read only block - if(Length <= disk->BlockSize - Offset) - { - VFS_ReadAt( disk->FD, base+Offset, Length, Buffer); - LEAVE('X', Length); - return Length; - } - - // Read first block - remLen = Length; - VFS_ReadAt( disk->FD, base + Offset, disk->BlockSize - Offset, Buffer); - remLen -= disk->BlockSize - Offset; - Buffer += disk->BlockSize - Offset; - block ++; - - // Read middle blocks - while(remLen > disk->BlockSize) - { - base = Ext2_int_GetBlockAddr(disk, inode.i_block, block); - if(base == 0) { - Warning("[EXT2 ] NULL Block Detected in INode 0x%llx", Node->Inode); - LEAVE('i', 0); - return 0; - } - VFS_ReadAt( disk->FD, base, disk->BlockSize, Buffer); - Buffer += disk->BlockSize; - remLen -= disk->BlockSize; - block ++; - } - - // Read last block - base = Ext2_int_GetBlockAddr(disk, inode.i_block, block); - VFS_ReadAt( disk->FD, base, remLen, Buffer); - - LEAVE('X', Length); - return Length; -} - -/** - * \fn Uint64 Ext2_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) - * \brief Write to a file - */ -Uint64 Ext2_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) -{ - tExt2_Disk *disk = Node->ImplPtr; - tExt2_Inode inode; - Uint64 base; - Uint64 retLen; - Uint block; - Uint64 allocSize; - int bNewBlocks = 0; - - Debug_HexDump("Ext2_Write", Buffer, Length); - - Ext2_int_GetInode(Node, &inode); - - // Get the ammount of space already allocated - // - Round size up to block size - // - block size is a power of two, so this will work - allocSize = (inode.i_size + disk->BlockSize) & ~(disk->BlockSize-1); - - // Are we writing to inside the allocated space? - if( Offset < allocSize ) - { - // Will we go out of it? - if(Offset + Length > allocSize) { - bNewBlocks = 1; - retLen = allocSize - Offset; - } else - retLen = Length; - - // Within the allocated space - block = Offset / disk->BlockSize; - Offset %= disk->BlockSize; - base = Ext2_int_GetBlockAddr(disk, inode.i_block, block); - - // Write only block (if only one) - if(Offset + retLen <= disk->BlockSize) { - VFS_WriteAt(disk->FD, base+Offset, retLen, Buffer); - if(!bNewBlocks) return Length; - goto addBlocks; // Ugh! A goto, but it seems unavoidable - } - - // Write First Block - VFS_WriteAt(disk->FD, base+Offset, disk->BlockSize-Offset, Buffer); - Buffer += disk->BlockSize-Offset; - retLen -= disk->BlockSize-Offset; - block ++; - - // Write middle blocks - while(retLen > disk->BlockSize) - { - base = Ext2_int_GetBlockAddr(disk, inode.i_block, block); - VFS_WriteAt(disk->FD, base, disk->BlockSize, Buffer); - Buffer += disk->BlockSize; - retLen -= disk->BlockSize; - block ++; - } - - // Write last block - base = Ext2_int_GetBlockAddr(disk, inode.i_block, block); - VFS_WriteAt(disk->FD, base, retLen, Buffer); - if(!bNewBlocks) return Length; // Writing in only allocated space - } - -addBlocks: - ///\todo Implement block allocation - Warning("[EXT2] File extending is not yet supported"); - - return 0; -} - -/** - * \fn void Ext2_CloseFile(tVFS_Node *Node) - * \brief Close a file (Remove it from the cache) - */ -void Ext2_CloseFile(tVFS_Node *Node) -{ - tExt2_Disk *disk = Node->ImplPtr; - Inode_UncacheNode(disk->CacheID, Node->Inode); - return ; -} - -/** - \fn char *Ext2_ReadDir(tVFS_Node *Node, int Pos) - \brief Reads a directory entry -*/ -char *Ext2_ReadDir(tVFS_Node *Node, int Pos) -{ - tExt2_Inode inode; - char namebuf[EXT2_NAME_LEN+1]; - tExt2_DirEnt dirent; - Uint64 Base; // Block's Base Address - int block = 0, ofs = 0; - int entNum = 0; - tExt2_Disk *disk = Node->ImplPtr; - Uint size; - - ENTER("pNode iPos", Node, Pos); - - // Read directory's inode - Ext2_int_GetInode(Node, &inode); - size = inode.i_size; - - LOG("inode.i_block[0] = 0x%x", inode.i_block[0]); - - // Find Entry - // Get First Block - // - Do this ourselves as it is a simple operation - Base = inode.i_block[0] * disk->BlockSize; - while(Pos -- && size > 0) - { - VFS_ReadAt( disk->FD, Base+ofs, sizeof(tExt2_DirEnt), &dirent); - ofs += dirent.rec_len; - size -= dirent.rec_len; - entNum ++; - - if(ofs >= disk->BlockSize) { - block ++; - if( ofs > disk->BlockSize ) { - Warning("[EXT2] Directory Entry %i of inode %i extends over a block boundary, ignoring", - entNum-1, Node->Inode); - } - ofs = 0; - Base = Ext2_int_GetBlockAddr( disk, inode.i_block, block ); - } - } - - // Check for the end of the list - if(size <= 0) { - LEAVE('n'); - return NULL; - } - - // Read Entry - VFS_ReadAt( disk->FD, Base+ofs, sizeof(tExt2_DirEnt), &dirent ); - //LOG("dirent.inode = %i", dirent.inode); - //LOG("dirent.rec_len = %i", dirent.rec_len); - //LOG("dirent.name_len = %i", dirent.name_len); - VFS_ReadAt( disk->FD, Base+ofs+sizeof(tExt2_DirEnt), dirent.name_len, namebuf ); - namebuf[ dirent.name_len ] = '\0'; // Cap off string - - - // Ignore . and .. (these are done in the VFS) - if( (namebuf[0] == '.' && namebuf[1] == '\0') - || (namebuf[0] == '.' && namebuf[1] == '.' && namebuf[2]=='\0')) { - LEAVE('p', VFS_SKIP); - return VFS_SKIP; // Skip - } - - LEAVE('s', namebuf); - // Create new node - return strdup(namebuf); -} - -/** - \fn tVFS_Node *Ext2_FindDir(tVFS_Node *node, char *filename) - \brief Gets information about a file - \param node vfs node - Parent Node - \param filename String - Name of file - \return VFS Node of file -*/ -tVFS_Node *Ext2_FindDir(tVFS_Node *Node, char *Filename) -{ - tExt2_Disk *disk = Node->ImplPtr; - tExt2_Inode inode; - char namebuf[EXT2_NAME_LEN+1]; - tExt2_DirEnt dirent; - Uint64 Base; // Block's Base Address - int block = 0, ofs = 0; - int entNum = 0; - Uint size; - - // Read directory's inode - Ext2_int_GetInode(Node, &inode); - size = inode.i_size; - - // Get First Block - // - Do this ourselves as it is a simple operation - Base = inode.i_block[0] * disk->BlockSize; - // Find File - while(size > 0) - { - VFS_ReadAt( disk->FD, Base+ofs, sizeof(tExt2_DirEnt), &dirent); - VFS_ReadAt( disk->FD, Base+ofs+sizeof(tExt2_DirEnt), dirent.name_len, namebuf ); - namebuf[ dirent.name_len ] = '\0'; // Cap off string - // If it matches, create a node and return it - if(strcmp(namebuf, Filename) == 0) - return Ext2_int_CreateNode( disk, dirent.inode, namebuf ); - // Increment pointers - ofs += dirent.rec_len; - size -= dirent.rec_len; - entNum ++; - - // Check for end of block - if(ofs >= disk->BlockSize) { - block ++; - if( ofs > disk->BlockSize ) { - Warning("[EXT2 ] Directory Entry %i of inode %i extends over a block boundary, ignoring", - entNum-1, Node->Inode); - } - ofs = 0; - Base = Ext2_int_GetBlockAddr( disk, inode.i_block, block ); - } - } - - return NULL; -} - -/** - * \fn int Ext2_MkNod(tVFS_Node *Parent, char *Name, Uint Flags) - * \brief Create a new node - */ -int Ext2_MkNod(tVFS_Node *Parent, char *Name, Uint Flags) -{ - return 0; -} - -//================================== -//= INTERNAL FUNCTIONS = -//================================== - - -/** - * \fn int Ext2_int_GetInode(tVFS_Node *Node, tExt2_Inode *Inode) - * \brief Gets the inode descriptor for a node - * \param Node node to get the Inode of - * \param Inode Destination - */ -int Ext2_int_GetInode(tVFS_Node *Node, tExt2_Inode *Inode) -{ - return Ext2_int_ReadInode(Node->ImplPtr, Node->Inode, Inode); -} - -/** - * \fn vfs_node *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeID, char *Name) - * \brief Create a new VFS Node - */ -tVFS_Node *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeID, char *Name) -{ - tExt2_Inode inode; - tVFS_Node retNode; - tVFS_Node *tmpNode; - - if( !Ext2_int_ReadInode(Disk, InodeID, &inode) ) - return NULL; - - if( (tmpNode = Inode_GetCache(Disk->CacheID, InodeID)) ) - return tmpNode; - - - // Set identifiers - retNode.Inode = InodeID; - retNode.ImplPtr = Disk; - - // Set file length - retNode.Size = inode.i_size; - - // Set Access Permissions - retNode.UID = inode.i_uid; - retNode.GID = inode.i_gid; - retNode.NumACLs = 3; - retNode.ACLs = VFS_UnixToAcessACL(inode.i_mode & 0777, inode.i_uid, inode.i_gid); - - // Set Function Pointers - retNode.Read = Ext2_Read; - retNode.Write = Ext2_Write; - retNode.Close = Ext2_CloseFile; - - switch(inode.i_mode & EXT2_S_IFMT) - { - // Symbolic Link - case EXT2_S_IFLNK: - retNode.Flags = VFS_FFLAG_SYMLINK; - break; - // Regular File - case EXT2_S_IFREG: - retNode.Flags = 0; - retNode.Size |= (Uint64)inode.i_dir_acl << 32; - break; - // Directory - case EXT2_S_IFDIR: - retNode.ReadDir = Ext2_ReadDir; - retNode.FindDir = Ext2_FindDir; - retNode.MkNod = Ext2_MkNod; - //retNode.Relink = Ext2_Relink; - retNode.Flags = VFS_FFLAG_DIRECTORY; - break; - // Unknown, Write protect and hide it to be safe - default: - retNode.Flags = VFS_FFLAG_READONLY;//|VFS_FFLAG_HIDDEN; - break; - } - - // Check if the file should be hidden - //if(Name[0] == '.') retNode.Flags |= VFS_FFLAG_HIDDEN; - - // Set Timestamps - retNode.ATime = now(); - retNode.MTime = inode.i_mtime * 1000; - retNode.CTime = inode.i_ctime * 1000; - - // Save in node cache and return saved node - return Inode_CacheNode(Disk->CacheID, &retNode); -} - -/** - * \fn int Ext2_int_ReadInode(tExt2_Disk *Disk, Uint InodeId, tExt2_Inode *Inode) - * \brief Read an inode into memory - */ -int Ext2_int_ReadInode(tExt2_Disk *Disk, Uint InodeId, tExt2_Inode *Inode) -{ - int group, subId; - - //LogF("Ext2_int_ReadInode: (Disk=%p, InodeId=%i, Inode=%p)", Disk, InodeId, Inode); - //ENTER("pDisk iInodeId pInode", Disk, InodeId, Inode); - - if(InodeId == 0) return 0; - - InodeId --; // Inodes are numbered starting at 1 - - group = InodeId / Disk->SuperBlock.s_inodes_per_group; - subId = InodeId % Disk->SuperBlock.s_inodes_per_group; - - //LOG("group=%i, subId = %i", group, subId); - - // Read Inode - VFS_ReadAt(Disk->FD, - Disk->Groups[group].bg_inode_table * Disk->BlockSize + sizeof(tExt2_Inode)*subId, - sizeof(tExt2_Inode), - Inode); - return 1; -} - -/** - * \fn Uint64 Ext2_int_GetBlockAddr(tExt2_Disk *Disk, Uint32 *Blocks, int BlockNum) - * \brief Get the address of a block from an inode's list - * \param Disk Disk information structure - * \param Blocks Pointer to an inode's block list - * \param BlockNum Block index in list - */ -Uint64 Ext2_int_GetBlockAddr(tExt2_Disk *Disk, Uint32 *Blocks, int BlockNum) -{ - Uint32 *iBlocks; - // Direct Blocks - if(BlockNum < 12) - return (Uint64)Blocks[BlockNum] * Disk->BlockSize; - - // Single Indirect Blocks - iBlocks = malloc( Disk->BlockSize ); - VFS_ReadAt(Disk->FD, (Uint64)Blocks[12]*Disk->BlockSize, Disk->BlockSize, iBlocks); - - BlockNum -= 12; - if(BlockNum < 256) { - BlockNum = iBlocks[BlockNum]; - free(iBlocks); - return (Uint64)BlockNum * Disk->BlockSize; - } - - // Double Indirect Blocks - if(BlockNum < 256*256) - { - VFS_ReadAt(Disk->FD, (Uint64)Blocks[13]*Disk->BlockSize, Disk->BlockSize, iBlocks); - VFS_ReadAt(Disk->FD, (Uint64)iBlocks[BlockNum/256]*Disk->BlockSize, Disk->BlockSize, iBlocks); - BlockNum = iBlocks[BlockNum%256]; - free(iBlocks); - return (Uint64)BlockNum * Disk->BlockSize; - } - // Triple Indirect Blocks - VFS_ReadAt(Disk->FD, (Uint64)Blocks[14]*Disk->BlockSize, Disk->BlockSize, iBlocks); - VFS_ReadAt(Disk->FD, (Uint64)iBlocks[BlockNum/(256*256)]*Disk->BlockSize, Disk->BlockSize, iBlocks); - VFS_ReadAt(Disk->FD, (Uint64)iBlocks[(BlockNum/256)%256]*Disk->BlockSize, Disk->BlockSize, iBlocks); - BlockNum = iBlocks[BlockNum%256]; - free(iBlocks); - return (Uint64)BlockNum * Disk->BlockSize; -} - -/** - * \fn Uint32 Ext2_int_AllocateInode(tExt2_Disk *Disk, Uint32 Parent) - * \brief Allocate an inode (from the current group preferably) - * \param Disk EXT2 Disk Information Structure - * \param Parent Inode ID of the parent (used to locate the child nearby) - */ -Uint32 Ext2_int_AllocateInode(tExt2_Disk *Disk, Uint32 Parent) -{ -// Uint block = (Parent - 1) / Disk->SuperBlock.s_inodes_per_group; - return 0; -} - -/** - * \fn Uint32 Ext2_int_AllocateBlock(tExt2_Disk *Disk, Uint32 PrevBlock) - * \brief Allocate a block from the best possible location - * \param Disk EXT2 Disk Information Structure - * \param PrevBlock Previous block ID in the file - */ -Uint32 Ext2_int_AllocateBlock(tExt2_Disk *Disk, Uint32 PrevBlock) -{ - int bpg = Disk->SuperBlock.s_blocks_per_group; - Uint blockgroup = PrevBlock / bpg; - Uint bitmap[Disk->BlockSize/sizeof(Uint)]; - Uint bitsperblock = 8*Disk->BlockSize; - int i, j = 0; - Uint block; - - // Are there any free blocks? - if(Disk->SuperBlock.s_free_blocks_count == 0) return 0; - - if(Disk->Groups[blockgroup].bg_free_blocks_count > 0) - { - // Search block group's bitmap - for(i = 0; i < bpg; i++) - { - // Get the block in the bitmap block - j = i & (bitsperblock-1); - - // Read in if needed - if(j == 0) { - VFS_ReadAt( - Disk->FD, - (Uint64)Disk->Groups[blockgroup].bg_block_bitmap + i / bitsperblock, - Disk->BlockSize, - bitmap - ); - } - - // Fast Check - if( bitmap[j/32] == -1 ) { - j = (j + 31) & ~31; - continue; - } - - // Is the bit set? - if( bitmap[j/32] & (1 << (j%32)) ) - continue; - - // Ooh! We found one - break; - } - if( i < bpg ) { - Warning("[EXT2 ] Inconsistency detected, Group Free Block count is non-zero when no free blocks exist"); - goto checkAll; // Search the entire filesystem for a free block - // Goto needed for neatness - } - - // Mark as used - bitmap[j/32] |= (1 << (j%32)); - VFS_WriteAt( - Disk->FD, - (Uint64)Disk->Groups[blockgroup].bg_block_bitmap + i / bitsperblock, - Disk->BlockSize, - bitmap - ); - block = i; - Disk->Groups[blockgroup].bg_free_blocks_count --; - } - else - { - checkAll: - Warning("[EXT2 ] TODO - Implement using blocks outside the current block group"); - return 0; - } - - // Reduce global count - Disk->SuperBlock.s_free_blocks_count --; - #if EXT2_UPDATE_WRITEBACK - Ext2_int_UpdateSuperblock(Disk); - #endif - - return block; -} - -/** - * \fn void Ext2_int_UpdateSuperblock(tExt2_Disk *Disk) - */ -void Ext2_int_UpdateSuperblock(tExt2_Disk *Disk) -{ - VFS_WriteAt(Disk->FD, 1024, 1024, &Disk->SuperBlock); -} diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..392ab5de --- /dev/null +++ b/Makefile @@ -0,0 +1,39 @@ +# +# Acess2 Core Makefile +# + +.PHONY: all clean + +all: + @echo === Kernel + @$(MAKE) all --no-print-directory -C Kernel + @echo === ld-acess.so + @$(MAKE) all --no-print-directory -C Usermode/Libraries/ld-acess.so_src + @echo === libacess.so + @$(MAKE) all --no-print-directory -C Usermode/Libraries/libacess.so_src + @echo === libgcc.so + @$(MAKE) all --no-print-directory -C Usermode/Libraries/libgcc.so_src + @echo === libc.so + @$(MAKE) all --no-print-directory -C Usermode/Libraries/libc.so_src + @echo === init + @$(MAKE) all --no-print-directory -C Usermode/Applications/init_src + @echo === login + @$(MAKE) all --no-print-directory -C Usermode/Applications/login_src + @echo === CLIShell + @$(MAKE) all --no-print-directory -C Usermode/Applications/CLIShell_src + @echo === cat + @$(MAKE) all --no-print-directory -C Usermode/Applications/cat_src + @echo === ls + @$(MAKE) all --no-print-directory -C Usermode/Applications/ls_src + +clean: + make clean --no-print-directory -C Kernel/ + make clean --no-print-directory -C Usermode/Libraries/ld-acess.so_src + make clean --no-print-directory -C Usermode/Libraries/libacess.so_src + make clean --no-print-directory -C Usermode/Libraries/libc.so_src + make clean --no-print-directory -C Usermode/Libraries/libgcc.so_src + make clean --no-print-directory -C Usermode/Applications/init_src + make clean --no-print-directory -C Usermode/Applications/login_src + make clean --no-print-directory -C Usermode/Applications/CLIShell_src + make clean --no-print-directory -C Usermode/Applications/cat_src + make clean --no-print-directory -C Usermode/Applications/ls_src diff --git a/Makefile.cfg b/Makefile.cfg index a8d3b200..18181a91 100644 --- a/Makefile.cfg +++ b/Makefile.cfg @@ -14,9 +14,9 @@ RMDIR = rm -rf ARCH = i386 ARCHDIR = x86 -FILESYSTEMS = fat ext2 +FILESYSTEMS = fat DRIVERS = ata_x86 -MODULES = FDD NE2000 BochsVBE +MODULES = FS_Ext2 FDD NE2000 BochsGA DISTROOT = /mnt/AcessHDD/Acess2 ACESSDIR = /home/hodgeja/Projects/Acess2 diff --git a/Modules/BochsVBE/Makefile b/Modules/BochsVBE/Makefile deleted file mode 100644 index add40181..00000000 --- a/Modules/BochsVBE/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -# -# - -OBJ = bochsvbe.o -NAME = BochsVBE - --include ../Makefile.tpl diff --git a/Modules/BochsVBE/bochsvbe.c b/Modules/BochsVBE/bochsvbe.c deleted file mode 100644 index 2fe01100..00000000 --- a/Modules/BochsVBE/bochsvbe.c +++ /dev/null @@ -1,451 +0,0 @@ -/** - * \file drv_bochsvbe.c - * \brief BGA (Bochs Graphic Adapter) Driver - * \note for Acess2 - * \warning This driver does NOT support the Bochs PCI VGA driver -*/ -#define DEBUG 0 -#include -#include -#include -#include -#include -#include -#include - -//#define INT static -#define INT - -// === TYPEDEFS === -typedef struct { - Uint16 width; - Uint16 height; - Uint16 bpp; - Uint16 flags; - Uint32 fbSize; -} t_bga_mode; - -// === CONSTANTS === -enum eMode_Flags { - MODEFLAG_TEXT = 1 -}; -#define BGA_LFB_MAXSIZE (1024*768*4) -#define VBE_DISPI_BANK_ADDRESS 0xA0000 -#define VBE_DISPI_LFB_PHYSICAL_ADDRESS 0xE0000000 -#define VBE_DISPI_IOPORT_INDEX 0x01CE -#define VBE_DISPI_IOPORT_DATA 0x01CF -#define VBE_DISPI_DISABLED 0x00 -#define VBE_DISPI_ENABLED 0x01 -#define VBE_DISPI_LFB_ENABLED 0x40 -#define VBE_DISPI_NOCLEARMEM 0x80 -enum { - VBE_DISPI_INDEX_ID, - VBE_DISPI_INDEX_XRES, - VBE_DISPI_INDEX_YRES, - VBE_DISPI_INDEX_BPP, - VBE_DISPI_INDEX_ENABLE, - VBE_DISPI_INDEX_BANK, - VBE_DISPI_INDEX_VIRT_WIDTH, - VBE_DISPI_INDEX_VIRT_HEIGHT, - VBE_DISPI_INDEX_X_OFFSET, - VBE_DISPI_INDEX_Y_OFFSET -}; - - -// === PROTOTYPES === -// Driver - int BGA_Install(char **Arguments); -void BGA_Uninstall(); -// Internal -void BGA_int_WriteRegister(Uint16 reg, Uint16 value); -Uint16 BGA_int_ReadRegister(Uint16 reg); -void BGA_int_SetBank(Uint16 bank); -void BGA_int_SetMode(Uint16 width, Uint16 height); - int BGA_int_UpdateMode(int id); - int BGA_int_FindMode(tVideo_IOCtl_Mode *info); - int BGA_int_ModeInfo(tVideo_IOCtl_Mode *info); - int BGA_int_MapFB(void *Dest); -// Filesystem -Uint64 BGA_Read(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer); -Uint64 BGA_Write(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer); - int BGA_Ioctl(tVFS_Node *node, int id, void *data); - -// === GLOBALS === -MODULE_DEFINE(0, 0x0032, BochsVBE, BGA_Install, NULL, NULL); -tDevFS_Driver gBGA_DriverStruct = { - NULL, "BochsGA", - { - .Read = BGA_Read, - .Write = BGA_Write, - .IOCtl = BGA_Ioctl - } -}; - int giBGA_CurrentMode = -1; - int giBGA_DriverId = -1; -Uint *gBGA_Framebuffer; -t_bga_mode gBGA_Modes[] = { - {}, - { 80,25, 12, MODEFLAG_TEXT, 80*25*8}, // 640 x 480 - {100,37, 12, MODEFLAG_TEXT, 100*37*8}, // 800 x 600 - {640,480,8, 0, 640*480}, - {640,480,32, 0, 640*480*4}, - {800,600,8, 0, 800*600}, - {800,600,32, 0, 800*600*4}, -}; -#define BGA_MODE_COUNT (sizeof(gBGA_Modes)/sizeof(gBGA_Modes[0])) - -// === CODE === -/** - * \fn int BGA_Install(char **Arguments) - */ -int BGA_Install(char **Arguments) -{ - int bga_version = 0; - - // Check BGA Version - bga_version = BGA_int_ReadRegister(VBE_DISPI_INDEX_ID); - // NOTE: This driver was written for 0xB0C4, but they seem to be backwards compatable - if(bga_version < 0xB0C4 || bga_version > 0xB0C5) { - Warning("[BGA ] Bochs Adapter Version is not 0xB0C4 or 0xB0C5, instead 0x%x", bga_version); - return 0; - } - - // Install Device - giBGA_DriverId = DevFS_AddDevice( &gBGA_DriverStruct ); - if(giBGA_DriverId == -1) { - Warning("[BGA ] Unable to register with DevFS, maybe already loaded?"); - return 0; - } - - // Map Framebuffer to hardware address - gBGA_Framebuffer = (void *) MM_MapHWPage(VBE_DISPI_LFB_PHYSICAL_ADDRESS, 768); // 768 pages (3Mb) - - return 1; -} - -/** - * \fn void BGA_Uninstall() - */ -void BGA_Uninstall() -{ - //DevFS_DelDevice( giBGA_DriverId ); - MM_UnmapHWPage( VBE_DISPI_LFB_PHYSICAL_ADDRESS, 768 ); -} - -/** - * \fn Uint64 BGA_Read(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer) - * \brief Read from the framebuffer - */ -Uint64 BGA_Read(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer) -{ - // Check Mode - if(giBGA_CurrentMode == -1) return -1; - - // Check Offset and Length against Framebuffer Size - if(off+len > gBGA_Modes[giBGA_CurrentMode].fbSize) - return -1; - - // Copy from Framebuffer - memcpy(buffer, (void*)((Uint)gBGA_Framebuffer + (Uint)off), len); - return len; -} - -/** - * \fn Uint64 BGA_Write(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer) - * \brief Write to the framebuffer - */ -Uint64 BGA_Write(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer) -{ - ENTER("xoff xlen", off, len); - - // Check Mode - if(giBGA_CurrentMode == -1) { - LEAVE('i', -1); - return -1; - } - - // Check Input against Frambuffer Size - if(off+len > gBGA_Modes[giBGA_CurrentMode].fbSize) { - LEAVE('i', -1); - return -1; - } - - // Text Mode - if( gBGA_Modes[giBGA_CurrentMode].flags & MODEFLAG_TEXT ) - { - tVT_Char *chars = buffer; - int pitch = gBGA_Modes[giBGA_CurrentMode].width * giVT_CharWidth; - Uint32 *dest; - off /= sizeof(tVT_Char); - dest = (void*)gBGA_Framebuffer; - dest += (off / gBGA_Modes[giBGA_CurrentMode].width) * giVT_CharHeight * pitch; - dest += (off % gBGA_Modes[giBGA_CurrentMode].width) * giVT_CharWidth; - len /= sizeof(tVT_Char); - while(len--) - { - VT_Font_Render( - chars->Ch, - dest, pitch, - VT_Colour12to24(chars->BGCol), - VT_Colour12to24(chars->FGCol) - ); - dest += giVT_CharWidth; - chars++; - } - } - else - { - Uint8 *destBuf = (Uint8*) ((Uint)gBGA_Framebuffer + (Uint)off); - - LOG("buffer = %p\n", buffer); - LOG("Updating Framebuffer (%p to %p)\n", - destBuf, destBuf + (Uint)len); - - - // Copy to Frambuffer - memcpy(destBuf, buffer, len); - - LOG("BGA Framebuffer updated\n"); - } - - LEAVE('i', len); - return len; -} - -/** - * \fn INT int BGA_Ioctl(tVFS_Node *node, int id, void *data) - * \brief Handle messages to the device - */ -INT int BGA_Ioctl(tVFS_Node *node, int id, void *data) -{ - int ret = -2; - ENTER("pNode iId pData", node, id, data); - - switch(id) - { - case DRV_IOCTL_TYPE: - ret = DRV_TYPE_VIDEO; - break; - case DRV_IOCTL_IDENT: - memcpy(data, "BGA1", 4); - ret = 1; - break; - case DRV_IOCTL_VERSION: - ret = 0x100; - break; - case DRV_IOCTL_LOOKUP: // TODO: Implement - ret = 0; - break; - - case VIDEO_IOCTL_SETMODE: - ret = BGA_int_UpdateMode(*(int*)(data)); - break; - - case VIDEO_IOCTL_GETMODE: - ret = giBGA_CurrentMode; - break; - - case VIDEO_IOCTL_FINDMODE: - ret = BGA_int_FindMode((tVideo_IOCtl_Mode*)data); - break; - - case VIDEO_IOCTL_MODEINFO: - ret = BGA_int_ModeInfo((tVideo_IOCtl_Mode*)data); - break; - - // Request Access to LFB - case VIDEO_IOCTL_REQLFB: - ret = BGA_int_MapFB( *(void**)data ); - break; - - default: - LEAVE('i', -2); - return -2; - } - - LEAVE('i', ret); - return ret; -} - -//== Internal Functions == -/** - * \fn void BGA_int_WriteRegister(Uint16 reg, Uint16 value) - * \brief Writes to a BGA register - */ -void BGA_int_WriteRegister(Uint16 reg, Uint16 value) -{ - outw(VBE_DISPI_IOPORT_INDEX, reg); - outw(VBE_DISPI_IOPORT_DATA, value); -} - -INT Uint16 BGA_int_ReadRegister(Uint16 reg) -{ - outw(VBE_DISPI_IOPORT_INDEX, reg); - return inw(VBE_DISPI_IOPORT_DATA); -} - -#if 0 -INT void BGA_int_SetBank(Uint16 bank) -{ - BGA_int_WriteRegister(VBE_DISPI_INDEX_BANK, bank); -} -#endif - -/** - * \fn void BGA_int_SetMode(Uint16 width, Uint16 height, Uint16 bpp) - * \brief Sets the video mode from the dimensions and bpp given - */ -void BGA_int_SetMode(Uint16 width, Uint16 height) -{ - ENTER("iwidth iheight ibpp", width, height, bpp); - BGA_int_WriteRegister(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_DISABLED); - BGA_int_WriteRegister(VBE_DISPI_INDEX_XRES, width); - BGA_int_WriteRegister(VBE_DISPI_INDEX_YRES, height); - BGA_int_WriteRegister(VBE_DISPI_INDEX_BPP, 32); - BGA_int_WriteRegister(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_ENABLED | VBE_DISPI_NOCLEARMEM | VBE_DISPI_LFB_ENABLED); - //BGA_int_WriteRegister(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_ENABLED | VBE_DISPI_NOCLEARMEM); - LEAVE('-'); -} - -/** - * \fn int BGA_int_UpdateMode(int id) - * \brief Set current vide mode given a mode id - */ -int BGA_int_UpdateMode(int id) -{ - // Sanity Check - if(id < 0 || id >= BGA_MODE_COUNT) return -1; - - // Check if it is a text mode - if( gBGA_Modes[id].flags & MODEFLAG_TEXT ) - BGA_int_SetMode( - gBGA_Modes[id].width*giVT_CharWidth, - gBGA_Modes[id].height*giVT_CharHeight); - else // Graphics? - BGA_int_SetMode( - gBGA_Modes[id].width, - gBGA_Modes[id].height); - - giBGA_CurrentMode = id; - return id; -} - -/** - * \fn int BGA_int_FindMode(tVideo_IOCtl_Mode *info) - * \brief Find a mode matching the given options - */ -int BGA_int_FindMode(tVideo_IOCtl_Mode *info) -{ - int i; - int best = 0, bestFactor = 1000; - int factor, tmp; - int rqdProduct = info->width * info->height * info->bpp; - - ENTER("pinfo", info); - LOG("info = {width:%i,height:%i,bpp:%i})\n", info->width, info->height, info->bpp); - - for(i = 0; i < BGA_MODE_COUNT; i++) - { - #if DEBUG >= 2 - LogF("Mode %i (%ix%ix%i), ", i, gBGA_Modes[i].width, gBGA_Modes[i].height, gBGA_Modes[i].bpp); - #endif - - // Check if this mode is the same type as what we want - if( !(gBGA_Modes[i].flags & MODEFLAG_TEXT) != !(info->flags & VIDEO_FLAG_TEXT) ) - continue; - - // Ooh! A perfect match - if(gBGA_Modes[i].width == info->width - && gBGA_Modes[i].height == info->height - && gBGA_Modes[i].bpp == info->bpp) - { - #if DEBUG >= 2 - LogF("Perfect!\n"); - #endif - best = i; - break; - } - - // If not, how close are we? - tmp = gBGA_Modes[i].width * gBGA_Modes[i].height * gBGA_Modes[i].bpp; - tmp -= rqdProduct; - tmp = tmp < 0 ? -tmp : tmp; // tmp = ABS(tmp) - factor = tmp * 100 / rqdProduct; - - #if DEBUG >= 2 - LogF("factor = %i\n", factor); - #endif - - if(factor < bestFactor) - { - bestFactor = factor; - best = i; - } - } - - info->id = best; - info->width = gBGA_Modes[best].width; - info->height = gBGA_Modes[best].height; - info->bpp = gBGA_Modes[best].bpp; - - info->flags = 0; - if(gBGA_Modes[best].flags & MODEFLAG_TEXT) - info->flags |= VIDEO_FLAG_TEXT; - - return best; -} - -/** - * \fn int BGA_int_ModeInfo(tVideo_IOCtl_Mode *info) - * \brief Get mode information - */ -int BGA_int_ModeInfo(tVideo_IOCtl_Mode *info) -{ - // Sanity Check - //if( !MM_IsUser( (Uint)info, sizeof(tVideo_IOCtl_Mode) ) ) { - // return -EINVAL; - //} - - if(info->id < 0 || info->id >= BGA_MODE_COUNT) return -1; - - info->width = gBGA_Modes[info->id].width; - info->height = gBGA_Modes[info->id].height; - info->bpp = gBGA_Modes[info->id].bpp; - - info->flags = 0; - if(gBGA_Modes[info->id].flags & MODEFLAG_TEXT) - info->flags |= VIDEO_FLAG_TEXT; - - return 1; -} - -/** - * \fn int BGA_int_MapFB(void *Dest) - * \brief Map the framebuffer into a process's space - * \param Dest User address to load to - */ -int BGA_int_MapFB(void *Dest) -{ - Uint i; - Uint pages; - - // Sanity Check - if((Uint)Dest > 0xC0000000) return 0; - if(gBGA_Modes[giBGA_CurrentMode].bpp < 15) return 0; // Only non-pallete modes are supported - - // Count required pages - pages = (gBGA_Modes[giBGA_CurrentMode].fbSize + 0xFFF) >> 12; - - // Check if there is space - for( i = 0; i < pages; i++ ) - { - if(MM_GetPhysAddr( (Uint)Dest + (i << 12) )) - return 0; - } - - // Map - for( i = 0; i < pages; i++ ) - MM_Map( (Uint)Dest + (i<<12), VBE_DISPI_LFB_PHYSICAL_ADDRESS + (i<<12) ); - - return 1; -} diff --git a/Modules/FS_Ext2/Makefile b/Modules/FS_Ext2/Makefile new file mode 100644 index 00000000..806e638c --- /dev/null +++ b/Modules/FS_Ext2/Makefile @@ -0,0 +1,7 @@ +# +# + +OBJ = ext2.o read.o dir.o write.o +NAME = FS_Ext2 + +-include ../Makefile.tpl diff --git a/Modules/FS_Ext2/dir.c b/Modules/FS_Ext2/dir.c new file mode 100644 index 00000000..5fe89336 --- /dev/null +++ b/Modules/FS_Ext2/dir.c @@ -0,0 +1,228 @@ +/* + * Acess OS + * Ext2 Driver Version 1 + */ +/** + * \file dir.c + * \brief Second Extended Filesystem Driver + * \todo Implement file full write support + */ +#define DEBUG 1 +#define VERBOSE 0 +#include "ext2_common.h" + + +// === PROTOTYPES === +char *Ext2_ReadDir(tVFS_Node *Node, int Pos); +tVFS_Node *Ext2_FindDir(tVFS_Node *Node, char *FileName); + int Ext2_MkNod(tVFS_Node *Node, char *Name, Uint Flags); +tVFS_Node *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeId, char *Name); + +// === CODE === +/** + \fn char *Ext2_ReadDir(tVFS_Node *Node, int Pos) + \brief Reads a directory entry +*/ +char *Ext2_ReadDir(tVFS_Node *Node, int Pos) +{ + tExt2_Inode inode; + char namebuf[EXT2_NAME_LEN+1]; + tExt2_DirEnt dirent; + Uint64 Base; // Block's Base Address + int block = 0, ofs = 0; + int entNum = 0; + tExt2_Disk *disk = Node->ImplPtr; + Uint size; + + ENTER("pNode iPos", Node, Pos); + + // Read directory's inode + Ext2_int_GetInode(Node, &inode); + size = inode.i_size; + + LOG("inode.i_block[0] = 0x%x", inode.i_block[0]); + + // Find Entry + // Get First Block + // - Do this ourselves as it is a simple operation + Base = inode.i_block[0] * disk->BlockSize; + while(Pos -- && size > 0) + { + VFS_ReadAt( disk->FD, Base+ofs, sizeof(tExt2_DirEnt), &dirent); + ofs += dirent.rec_len; + size -= dirent.rec_len; + entNum ++; + + if(ofs >= disk->BlockSize) { + block ++; + if( ofs > disk->BlockSize ) { + Warning("[EXT2] Directory Entry %i of inode %i extends over a block boundary, ignoring", + entNum-1, Node->Inode); + } + ofs = 0; + Base = Ext2_int_GetBlockAddr( disk, inode.i_block, block ); + } + } + + // Check for the end of the list + if(size <= 0) { + LEAVE('n'); + return NULL; + } + + // Read Entry + VFS_ReadAt( disk->FD, Base+ofs, sizeof(tExt2_DirEnt), &dirent ); + //LOG("dirent.inode = %i", dirent.inode); + //LOG("dirent.rec_len = %i", dirent.rec_len); + //LOG("dirent.name_len = %i", dirent.name_len); + VFS_ReadAt( disk->FD, Base+ofs+sizeof(tExt2_DirEnt), dirent.name_len, namebuf ); + namebuf[ dirent.name_len ] = '\0'; // Cap off string + + + // Ignore . and .. (these are done in the VFS) + if( (namebuf[0] == '.' && namebuf[1] == '\0') + || (namebuf[0] == '.' && namebuf[1] == '.' && namebuf[2]=='\0')) { + LEAVE('p', VFS_SKIP); + return VFS_SKIP; // Skip + } + + LEAVE('s', namebuf); + // Create new node + return strdup(namebuf); +} + +/** + \fn tVFS_Node *Ext2_FindDir(tVFS_Node *node, char *filename) + \brief Gets information about a file + \param node vfs node - Parent Node + \param filename String - Name of file + \return VFS Node of file +*/ +tVFS_Node *Ext2_FindDir(tVFS_Node *Node, char *Filename) +{ + tExt2_Disk *disk = Node->ImplPtr; + tExt2_Inode inode; + char namebuf[EXT2_NAME_LEN+1]; + tExt2_DirEnt dirent; + Uint64 Base; // Block's Base Address + int block = 0, ofs = 0; + int entNum = 0; + Uint size; + + // Read directory's inode + Ext2_int_GetInode(Node, &inode); + size = inode.i_size; + + // Get First Block + // - Do this ourselves as it is a simple operation + Base = inode.i_block[0] * disk->BlockSize; + // Find File + while(size > 0) + { + VFS_ReadAt( disk->FD, Base+ofs, sizeof(tExt2_DirEnt), &dirent); + VFS_ReadAt( disk->FD, Base+ofs+sizeof(tExt2_DirEnt), dirent.name_len, namebuf ); + namebuf[ dirent.name_len ] = '\0'; // Cap off string + // If it matches, create a node and return it + if(strcmp(namebuf, Filename) == 0) + return Ext2_int_CreateNode( disk, dirent.inode, namebuf ); + // Increment pointers + ofs += dirent.rec_len; + size -= dirent.rec_len; + entNum ++; + + // Check for end of block + if(ofs >= disk->BlockSize) { + block ++; + if( ofs > disk->BlockSize ) { + Warning("[EXT2 ] Directory Entry %i of inode %i extends over a block boundary, ignoring", + entNum-1, Node->Inode); + } + ofs = 0; + Base = Ext2_int_GetBlockAddr( disk, inode.i_block, block ); + } + } + + return NULL; +} + +/** + * \fn int Ext2_MkNod(tVFS_Node *Parent, char *Name, Uint Flags) + * \brief Create a new node + */ +int Ext2_MkNod(tVFS_Node *Parent, char *Name, Uint Flags) +{ + return 0; +} + +// ---- INTERNAL FUNCTIONS ---- +/** + * \fn vfs_node *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeID, char *Name) + * \brief Create a new VFS Node + */ +tVFS_Node *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeID, char *Name) +{ + tExt2_Inode inode; + tVFS_Node retNode; + tVFS_Node *tmpNode; + + if( !Ext2_int_ReadInode(Disk, InodeID, &inode) ) + return NULL; + + if( (tmpNode = Inode_GetCache(Disk->CacheID, InodeID)) ) + return tmpNode; + + + // Set identifiers + retNode.Inode = InodeID; + retNode.ImplPtr = Disk; + + // Set file length + retNode.Size = inode.i_size; + + // Set Access Permissions + retNode.UID = inode.i_uid; + retNode.GID = inode.i_gid; + retNode.NumACLs = 3; + retNode.ACLs = VFS_UnixToAcessACL(inode.i_mode & 0777, inode.i_uid, inode.i_gid); + + // Set Function Pointers + retNode.Read = Ext2_Read; + retNode.Write = Ext2_Write; + retNode.Close = Ext2_CloseFile; + + switch(inode.i_mode & EXT2_S_IFMT) + { + // Symbolic Link + case EXT2_S_IFLNK: + retNode.Flags = VFS_FFLAG_SYMLINK; + break; + // Regular File + case EXT2_S_IFREG: + retNode.Flags = 0; + retNode.Size |= (Uint64)inode.i_dir_acl << 32; + break; + // Directory + case EXT2_S_IFDIR: + retNode.ReadDir = Ext2_ReadDir; + retNode.FindDir = Ext2_FindDir; + retNode.MkNod = Ext2_MkNod; + //retNode.Relink = Ext2_Relink; + retNode.Flags = VFS_FFLAG_DIRECTORY; + break; + // Unknown, Write protect and hide it to be safe + default: + retNode.Flags = VFS_FFLAG_READONLY;//|VFS_FFLAG_HIDDEN; + break; + } + + // Check if the file should be hidden + //if(Name[0] == '.') retNode.Flags |= VFS_FFLAG_HIDDEN; + + // Set Timestamps + retNode.ATime = now(); + retNode.MTime = inode.i_mtime * 1000; + retNode.CTime = inode.i_ctime * 1000; + + // Save in node cache and return saved node + return Inode_CacheNode(Disk->CacheID, &retNode); +} diff --git a/Modules/FS_Ext2/ext2.c b/Modules/FS_Ext2/ext2.c new file mode 100644 index 00000000..81dcef0b --- /dev/null +++ b/Modules/FS_Ext2/ext2.c @@ -0,0 +1,309 @@ +/* + * Acess OS + * Ext2 Driver Version 1 + */ +/** + * \file fs/ext2.c + * \brief Second Extended Filesystem Driver + * \todo Implement file full write support + */ +#define DEBUG 1 +#define VERBOSE 0 +#include "ext2_common.h" +#include + +// === PROTOTYPES === + int Ext2_Install(char **Arguments); +// Interface Functions +tVFS_Node *Ext2_InitDevice(char *Device, char **Options); +void Ext2_Unmount(tVFS_Node *Node); +void Ext2_CloseFile(tVFS_Node *Node); +// Internal Helpers + int Ext2_int_GetInode(tVFS_Node *Node, tExt2_Inode *Inode); +Uint64 Ext2_int_GetBlockAddr(tExt2_Disk *Disk, Uint32 *Blocks, int BlockNum); +Uint32 Ext2_int_AllocateInode(tExt2_Disk *Disk, Uint32 Parent); +void Ext2_int_UpdateSuperblock(tExt2_Disk *Disk); + +// === SEMI-GLOBALS === +MODULE_DEFINE(0, 0x5B /*v0.90*/, FS_Ext2, Ext2_Install, NULL); +tExt2_Disk gExt2_disks[6]; + int giExt2_count = 0; +tVFS_Driver gExt2_FSInfo = { + "ext2", 0, Ext2_InitDevice, Ext2_Unmount, NULL + }; + +// === CODE === + +/** + * \fn int Ext2_Install(char **Arguments) + * \brief Install the Ext2 Filesystem Driver + */ +int Ext2_Install(char **Arguments) +{ + VFS_AddDriver( &gExt2_FSInfo ); + return 1; +} + +/** + \fn tVFS_Node *Ext2_InitDevice(char *Device, char **Options) + \brief Initializes a device to be read by by the driver + \param Device String - Device to read from + \param Options NULL Terminated array of option strings + \return Root Node +*/ +tVFS_Node *Ext2_InitDevice(char *Device, char **Options) +{ + tExt2_Disk *disk; + int fd; + int groupCount; + tExt2_SuperBlock sb; + tExt2_Inode inode; + + ENTER("sDevice pOptions", Device, Options); + + // Open Disk + fd = VFS_Open(Device, VFS_OPENFLAG_READ|VFS_OPENFLAG_WRITE); //Open Device + if(fd == -1) { + Warning("[EXT2 ] Unable to open '%s'", Device); + LEAVE('n'); + return NULL; + } + + // Read Superblock at offset 1024 + VFS_ReadAt(fd, 1024, 1024, &sb); // Read Superblock + + // Sanity Check Magic value + if(sb.s_magic != 0xEF53) { + Warning("[EXT2 ] Volume '%s' is not an EXT2 volume", Device); + VFS_Close(fd); + LEAVE('n'); + return NULL; + } + + // Get Group count + groupCount = DivUp(sb.s_blocks_count, sb.s_blocks_per_group); + LOG("groupCount = %i", groupCount); + + // Allocate Disk Information + disk = malloc(sizeof(tExt2_Disk) + sizeof(tExt2_Group)*groupCount); + if(!disk) { + Warning("[EXT2 ] Unable to allocate disk structure"); + VFS_Close(fd); + LEAVE('n'); + return NULL; + } + disk->FD = fd; + memcpy(&disk->SuperBlock, &sb, 1024); + disk->GroupCount = groupCount; + + // Get an inode cache handle + disk->CacheID = Inode_GetHandle(); + + // Get Block Size + LOG("s_log_block_size = 0x%x", sb.s_log_block_size); + disk->BlockSize = 1024 << sb.s_log_block_size; + + // Read Group Information + VFS_ReadAt( + disk->FD, + sb.s_first_data_block * disk->BlockSize + 1024, + sizeof(tExt2_Group)*groupCount, + disk->Groups + ); + + #if VERBOSE + LOG("Block Group 0"); + LOG(".bg_block_bitmap = 0x%x", disk->Groups[0].bg_block_bitmap); + LOG(".bg_inode_bitmap = 0x%x", disk->Groups[0].bg_inode_bitmap); + LOG(".bg_inode_table = 0x%x", disk->Groups[0].bg_inode_table); + LOG("Block Group 1"); + LOG(".bg_block_bitmap = 0x%x", disk->Groups[1].bg_block_bitmap); + LOG(".bg_inode_bitmap = 0x%x", disk->Groups[1].bg_inode_bitmap); + LOG(".bg_inode_table = 0x%x", disk->Groups[1].bg_inode_table); + #endif + + // Get root Inode + Ext2_int_ReadInode(disk, 2, &inode); + + // Create Root Node + memset(&disk->RootNode, 0, sizeof(tVFS_Node)); + disk->RootNode.Inode = 2; // Root inode ID + disk->RootNode.ImplPtr = disk; // Save disk pointer + disk->RootNode.Size = -1; // Fill in later (on readdir) + disk->RootNode.Flags = VFS_FFLAG_DIRECTORY; + + disk->RootNode.ReadDir = Ext2_ReadDir; + disk->RootNode.FindDir = Ext2_FindDir; + //disk->RootNode.Relink = Ext2_Relink; + + // Complete root node + disk->RootNode.UID = inode.i_uid; + disk->RootNode.GID = inode.i_gid; + disk->RootNode.NumACLs = 1; + disk->RootNode.ACLs = &gVFS_ACL_EveryoneRW; + + #if DEBUG + LOG("inode.i_size = 0x%x", inode.i_size); + LOG("inode.i_block[0] = 0x%x", inode.i_block[0]); + #endif + + LEAVE('p', &disk->RootNode); + return &disk->RootNode; +} + +/** + * \fn void Ext2_Unmount(tVFS_Node *Node) + * \brief Close a mounted device + */ +void Ext2_Unmount(tVFS_Node *Node) +{ + tExt2_Disk *disk = Node->ImplPtr; + + VFS_Close( disk->FD ); + Inode_ClearCache( disk->CacheID ); + memset(disk, 0, sizeof(tExt2_Disk)+disk->GroupCount*sizeof(tExt2_Group)); + free(disk); +} + +/** + * \fn void Ext2_CloseFile(tVFS_Node *Node) + * \brief Close a file (Remove it from the cache) + */ +void Ext2_CloseFile(tVFS_Node *Node) +{ + tExt2_Disk *disk = Node->ImplPtr; + Inode_UncacheNode(disk->CacheID, Node->Inode); + return ; +} + +//================================== +//= INTERNAL FUNCTIONS = +//================================== + + +/** + * \fn int Ext2_int_GetInode(tVFS_Node *Node, tExt2_Inode *Inode) + * \brief Gets the inode descriptor for a node + * \param Node node to get the Inode of + * \param Inode Destination + */ +int Ext2_int_GetInode(tVFS_Node *Node, tExt2_Inode *Inode) +{ + return Ext2_int_ReadInode(Node->ImplPtr, Node->Inode, Inode); +} + +/** + * \fn int Ext2_int_ReadInode(tExt2_Disk *Disk, Uint InodeId, tExt2_Inode *Inode) + * \brief Read an inode into memory + */ +int Ext2_int_ReadInode(tExt2_Disk *Disk, Uint InodeId, tExt2_Inode *Inode) +{ + int group, subId; + + //LogF("Ext2_int_ReadInode: (Disk=%p, InodeId=%i, Inode=%p)", Disk, InodeId, Inode); + //ENTER("pDisk iInodeId pInode", Disk, InodeId, Inode); + + if(InodeId == 0) return 0; + + InodeId --; // Inodes are numbered starting at 1 + + group = InodeId / Disk->SuperBlock.s_inodes_per_group; + subId = InodeId % Disk->SuperBlock.s_inodes_per_group; + + //LOG("group=%i, subId = %i", group, subId); + + // Read Inode + VFS_ReadAt(Disk->FD, + Disk->Groups[group].bg_inode_table * Disk->BlockSize + sizeof(tExt2_Inode)*subId, + sizeof(tExt2_Inode), + Inode); + return 1; +} + +/** + * \fn Uint64 Ext2_int_GetBlockAddr(tExt2_Disk *Disk, Uint32 *Blocks, int BlockNum) + * \brief Get the address of a block from an inode's list + * \param Disk Disk information structure + * \param Blocks Pointer to an inode's block list + * \param BlockNum Block index in list + */ +Uint64 Ext2_int_GetBlockAddr(tExt2_Disk *Disk, Uint32 *Blocks, int BlockNum) +{ + Uint32 *iBlocks; + // Direct Blocks + if(BlockNum < 12) + return (Uint64)Blocks[BlockNum] * Disk->BlockSize; + + // Single Indirect Blocks + iBlocks = malloc( Disk->BlockSize ); + VFS_ReadAt(Disk->FD, (Uint64)Blocks[12]*Disk->BlockSize, Disk->BlockSize, iBlocks); + + BlockNum -= 12; + if(BlockNum < 256) { + BlockNum = iBlocks[BlockNum]; + free(iBlocks); + return (Uint64)BlockNum * Disk->BlockSize; + } + + // Double Indirect Blocks + if(BlockNum < 256*256) + { + VFS_ReadAt(Disk->FD, (Uint64)Blocks[13]*Disk->BlockSize, Disk->BlockSize, iBlocks); + VFS_ReadAt(Disk->FD, (Uint64)iBlocks[BlockNum/256]*Disk->BlockSize, Disk->BlockSize, iBlocks); + BlockNum = iBlocks[BlockNum%256]; + free(iBlocks); + return (Uint64)BlockNum * Disk->BlockSize; + } + // Triple Indirect Blocks + VFS_ReadAt(Disk->FD, (Uint64)Blocks[14]*Disk->BlockSize, Disk->BlockSize, iBlocks); + VFS_ReadAt(Disk->FD, (Uint64)iBlocks[BlockNum/(256*256)]*Disk->BlockSize, Disk->BlockSize, iBlocks); + VFS_ReadAt(Disk->FD, (Uint64)iBlocks[(BlockNum/256)%256]*Disk->BlockSize, Disk->BlockSize, iBlocks); + BlockNum = iBlocks[BlockNum%256]; + free(iBlocks); + return (Uint64)BlockNum * Disk->BlockSize; +} + +/** + * \fn Uint32 Ext2_int_AllocateInode(tExt2_Disk *Disk, Uint32 Parent) + * \brief Allocate an inode (from the current group preferably) + * \param Disk EXT2 Disk Information Structure + * \param Parent Inode ID of the parent (used to locate the child nearby) + */ +Uint32 Ext2_int_AllocateInode(tExt2_Disk *Disk, Uint32 Parent) +{ +// Uint block = (Parent - 1) / Disk->SuperBlock.s_inodes_per_group; + return 0; +} + +/** + * \fn void Ext2_int_UpdateSuperblock(tExt2_Disk *Disk) + * \brief Updates the superblock + */ +void Ext2_int_UpdateSuperblock(tExt2_Disk *Disk) +{ + int bpg = Disk->SuperBlock.s_blocks_per_group; + int ngrp = Disk->SuperBlock.s_blocks_count / bpg; + int i; + + // Update Primary + VFS_WriteAt(Disk->FD, 1024, 1024, &Disk->SuperBlock); + + // Secondaries + // at Block Group 1, 3^n, 5^n, 7^n + + // 1 + if(ngrp <= 1) return; + VFS_WriteAt(Disk->FD, 1*bpg*Disk->BlockSize, 1024, &Disk->SuperBlock); + + // Powers of 3 + for( i = 3; i < ngrp; i *= 3 ) + VFS_WriteAt(Disk->FD, i*bpg*Disk->BlockSize, 1024, &Disk->SuperBlock); + + // Powers of 5 + for( i = 5; i < ngrp; i *= 5 ) + VFS_WriteAt(Disk->FD, i*bpg*Disk->BlockSize, 1024, &Disk->SuperBlock); + + // Powers of 7 + for( i = 7; i < ngrp; i *= 7 ) + VFS_WriteAt(Disk->FD, i*bpg*Disk->BlockSize, 1024, &Disk->SuperBlock); +} diff --git a/Modules/FS_Ext2/ext2_common.h b/Modules/FS_Ext2/ext2_common.h new file mode 100644 index 00000000..07e838e5 --- /dev/null +++ b/Modules/FS_Ext2/ext2_common.h @@ -0,0 +1,46 @@ +/* + * Acess OS + * Ext2 Driver Version 1 + */ +/** + * \file ext2_common.h + * \brief Second Extended Filesystem Driver + */ +#ifndef _EXT2_COMMON_H +#define _EXT2_COMMON_H +#include +#include +#include "ext2fs.h" + +#define EXT2_UPDATE_WRITEBACK 1 + +// === STRUCTURES === +typedef struct { + int FD; + int CacheID; + tVFS_Node RootNode; + + tExt2_SuperBlock SuperBlock; + int BlockSize; + + int GroupCount; + tExt2_Group Groups[]; +} tExt2_Disk; + +// === FUNCTIONS === +// --- Common --- +extern void Ext2_CloseFile(tVFS_Node *Node); +extern int Ext2_int_GetInode(tVFS_Node *Node, tExt2_Inode *Inode); +extern Uint64 Ext2_int_GetBlockAddr(tExt2_Disk *Disk, Uint32 *Blocks, int BlockNum); +extern void Ext2_int_UpdateSuperblock(tExt2_Disk *Disk); +// --- Dir --- +extern char *Ext2_ReadDir(tVFS_Node *Node, int Pos); +extern tVFS_Node *Ext2_FindDir(tVFS_Node *Node, char *FileName); +extern int Ext2_MkNod(tVFS_Node *Node, char *Name, Uint Flags); +// --- Read --- +extern Uint64 Ext2_Read(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer); +extern int Ext2_int_ReadInode(tExt2_Disk *Disk, Uint InodeId, tExt2_Inode *Inode); +// --- Write --- +extern Uint64 Ext2_Write(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer); + +#endif diff --git a/Kernel/vfs/fs/fs_ext2.h b/Modules/FS_Ext2/ext2fs.h similarity index 94% rename from Kernel/vfs/fs/fs_ext2.h rename to Modules/FS_Ext2/ext2fs.h index f7c9ae15..8fd87ce4 100644 --- a/Kernel/vfs/fs/fs_ext2.h +++ b/Modules/FS_Ext2/ext2fs.h @@ -1,8 +1,10 @@ /** * Acess2 - * \file fs_ext2.h + * \file ext2fs.h * \brief EXT2 Filesystem Driver */ +#ifndef _EXT2FS_H_ +#define _EXT2FS_H_ /** \name Inode Flag Values @@ -88,7 +90,7 @@ struct ext2_inode_s { Uint32 i_dtime; //!< Deletion Time Uint16 i_gid; //!< Group Id Uint16 i_links_count; //!< Links count - Uint32 i_blocks; //!< Blocks count + Uint32 i_blocks; //!< Number of blocks allocated for the file Uint32 i_flags; //!< File flags union { Uint32 linux_reserved1; //!< Linux: Reserved @@ -150,3 +152,5 @@ struct ext2_dir_entry_s { Uint8 type; //!< File Type char name[]; //!< File name }; + +#endif diff --git a/Modules/FS_Ext2/read.c b/Modules/FS_Ext2/read.c new file mode 100644 index 00000000..cb6649a6 --- /dev/null +++ b/Modules/FS_Ext2/read.c @@ -0,0 +1,89 @@ +/* + * Acess OS + * Ext2 Driver Version 1 + */ +/** + * \file read.c + * \brief Second Extended Filesystem Driver + * \todo Implement file full write support + */ +#define DEBUG 1 +#define VERBOSE 0 +#include "ext2_common.h" + +// === PROTOTYPES === +Uint64 Ext2_Read(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer); + int Ext2_int_ReadInode(tExt2_Disk *Disk, Uint InodeId, tExt2_Inode *Inode); + +// === CODE === +/** + * \fn Uint64 Ext2_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) + * \brief Read from a file + */ +Uint64 Ext2_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) +{ + tExt2_Disk *disk = Node->ImplPtr; + tExt2_Inode inode; + Uint64 base; + Uint block; + Uint64 remLen; + + ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer); + + // Get Inode + Ext2_int_GetInode(Node, &inode); + + // Sanity Checks + if(Offset >= inode.i_size) { + LEAVE('i', 0); + return 0; + } + if(Offset + Length > inode.i_size) + Length = inode.i_size - Offset; + + block = Offset / disk->BlockSize; + Offset = Offset / disk->BlockSize; + base = Ext2_int_GetBlockAddr(disk, inode.i_block, block); + if(base == 0) { + Warning("[EXT2 ] NULL Block Detected in INode 0x%llx", Node->Inode); + LEAVE('i', 0); + return 0; + } + + // Read only block + if(Length <= disk->BlockSize - Offset) + { + VFS_ReadAt( disk->FD, base+Offset, Length, Buffer); + LEAVE('X', Length); + return Length; + } + + // Read first block + remLen = Length; + VFS_ReadAt( disk->FD, base + Offset, disk->BlockSize - Offset, Buffer); + remLen -= disk->BlockSize - Offset; + Buffer += disk->BlockSize - Offset; + block ++; + + // Read middle blocks + while(remLen > disk->BlockSize) + { + base = Ext2_int_GetBlockAddr(disk, inode.i_block, block); + if(base == 0) { + Warning("[EXT2 ] NULL Block Detected in INode 0x%llx", Node->Inode); + LEAVE('i', 0); + return 0; + } + VFS_ReadAt( disk->FD, base, disk->BlockSize, Buffer); + Buffer += disk->BlockSize; + remLen -= disk->BlockSize; + block ++; + } + + // Read last block + base = Ext2_int_GetBlockAddr(disk, inode.i_block, block); + VFS_ReadAt( disk->FD, base, remLen, Buffer); + + LEAVE('X', Length); + return Length; +} diff --git a/Modules/FS_Ext2/write.c b/Modules/FS_Ext2/write.c new file mode 100644 index 00000000..f3fdc6b3 --- /dev/null +++ b/Modules/FS_Ext2/write.c @@ -0,0 +1,176 @@ +/* + * Acess OS + * Ext2 Driver Version 1 + */ +/** + * \file write.c + * \brief Second Extended Filesystem Driver + * \todo Implement file full write support + */ +#define DEBUG 1 +#define VERBOSE 0 +#include "ext2_common.h" + +// === PROTOYPES === +Uint64 Ext2_Write(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer); +Uint32 Ext2_int_AllocateBlock(tExt2_Disk *Disk, Uint32 PrevBlock); + +// === CODE === +/** + * \fn Uint64 Ext2_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) + * \brief Write to a file + */ +Uint64 Ext2_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) +{ + tExt2_Disk *disk = Node->ImplPtr; + tExt2_Inode inode; + Uint64 base; + Uint64 retLen; + Uint block; + Uint64 allocSize; + int bNewBlocks = 0; + + Debug_HexDump("Ext2_Write", Buffer, Length); + + Ext2_int_GetInode(Node, &inode); + + // Get the ammount of space already allocated + // - Round size up to block size + // - block size is a power of two, so this will work + allocSize = (inode.i_size + disk->BlockSize) & ~(disk->BlockSize-1); + + // Are we writing to inside the allocated space? + if( Offset < allocSize ) + { + // Will we go out of it? + if(Offset + Length > allocSize) { + bNewBlocks = 1; + retLen = allocSize - Offset; + } else + retLen = Length; + + // Within the allocated space + block = Offset / disk->BlockSize; + Offset %= disk->BlockSize; + base = Ext2_int_GetBlockAddr(disk, inode.i_block, block); + + // Write only block (if only one) + if(Offset + retLen <= disk->BlockSize) { + VFS_WriteAt(disk->FD, base+Offset, retLen, Buffer); + if(!bNewBlocks) return Length; + goto addBlocks; // Ugh! A goto, but it seems unavoidable + } + + // Write First Block + VFS_WriteAt(disk->FD, base+Offset, disk->BlockSize-Offset, Buffer); + Buffer += disk->BlockSize-Offset; + retLen -= disk->BlockSize-Offset; + block ++; + + // Write middle blocks + while(retLen > disk->BlockSize) + { + base = Ext2_int_GetBlockAddr(disk, inode.i_block, block); + VFS_WriteAt(disk->FD, base, disk->BlockSize, Buffer); + Buffer += disk->BlockSize; + retLen -= disk->BlockSize; + block ++; + } + + // Write last block + base = Ext2_int_GetBlockAddr(disk, inode.i_block, block); + VFS_WriteAt(disk->FD, base, retLen, Buffer); + if(!bNewBlocks) return Length; // Writing in only allocated space + } + +addBlocks: + ///\todo Implement block allocation + Warning("[EXT2] File extending is not yet supported"); + + return 0; +} + +/** + * \fn Uint32 Ext2_int_AllocateBlock(tExt2_Disk *Disk, Uint32 PrevBlock) + * \brief Allocate a block from the best possible location + * \param Disk EXT2 Disk Information Structure + * \param PrevBlock Previous block ID in the file + */ +Uint32 Ext2_int_AllocateBlock(tExt2_Disk *Disk, Uint32 PrevBlock) +{ + int bpg = Disk->SuperBlock.s_blocks_per_group; + Uint blockgroup = PrevBlock / bpg; + Uint bitmap[Disk->BlockSize/sizeof(Uint)]; + Uint bitsperblock = 8*Disk->BlockSize; + int i, j = 0; + Uint block; + + // Are there any free blocks? + if(Disk->SuperBlock.s_free_blocks_count == 0) return 0; + + if(Disk->Groups[blockgroup].bg_free_blocks_count > 0) + { + // Search block group's bitmap + for(i = 0; i < bpg; i++) + { + // Get the block in the bitmap block + j = i & (bitsperblock-1); + + // Read in if needed + if(j == 0) { + VFS_ReadAt( + Disk->FD, + (Uint64)Disk->Groups[blockgroup].bg_block_bitmap + i / bitsperblock, + Disk->BlockSize, + bitmap + ); + } + + // Fast Check + if( bitmap[j/32] == -1 ) { + j = (j + 31) & ~31; + continue; + } + + // Is the bit set? + if( bitmap[j/32] & (1 << (j%32)) ) + continue; + + // Ooh! We found one + break; + } + if( i < bpg ) { + Warning("[EXT2 ] Inconsistency detected, Group Free Block count is non-zero when no free blocks exist"); + goto checkAll; // Search the entire filesystem for a free block + // Goto needed for neatness + } + + // Mark as used + bitmap[j/32] |= (1 << (j%32)); + VFS_WriteAt( + Disk->FD, + (Uint64)Disk->Groups[blockgroup].bg_block_bitmap + i / bitsperblock, + Disk->BlockSize, + bitmap + ); + block = i; + Disk->Groups[blockgroup].bg_free_blocks_count --; + #if EXT2_UPDATE_WRITEBACK + //Ext2_int_UpdateBlockGroup(blockgroup); + #endif + } + else + { + checkAll: + Warning("[EXT2 ] TODO - Implement using blocks outside the current block group"); + return 0; + } + + // Reduce global count + Disk->SuperBlock.s_free_blocks_count --; + #if EXT2_UPDATE_WRITEBACK + Ext2_int_UpdateSuperblock(Disk); + #endif + + return block; +} diff --git a/Modules/USB/uhci.c b/Modules/USB/uhci.c index 65037ef0..2f1950a6 100644 --- a/Modules/USB/uhci.c +++ b/Modules/USB/uhci.c @@ -60,8 +60,8 @@ int UHCI_Initialise() if(i == MAX_CONTROLLERS) { Warning("[UHCI ] Over "EXPAND_STR(MAX_CONTROLLERS)" UHCI controllers detected, ignoring rest"); } - LEAVE('i', 0); - return 0; + LEAVE('i', i); + return i; } /** @@ -71,13 +71,13 @@ int UHCI_Initialise() void UHCI_Cleanup() { } - -/** - * \fn int UHCI_IOCtl(tVFS_Node *Node, int ID, void *Data) - */ -int UHCI_IOCtl(tVFS_Node *Node, int ID, void *Data) -{ - return 0; + +/** + * \brief Sends a packet to a device endpoint + */ +int UHCI_SendPacket(int ControllerId, int Device, int Endpoint, void *Data, int Length) +{ + return 0; } // === INTERNAL FUNCTIONS === diff --git a/Modules/USB/usb.h b/Modules/USB/usb.h index 3e503ec4..1ccf98c7 100644 --- a/Modules/USB/usb.h +++ b/Modules/USB/usb.h @@ -9,6 +9,68 @@ typedef struct sUSBHost tUSBHost; typedef struct sUSBDevice tUSBDevice; +// === CONSTANTS === +enum eUSB_PIDs +{ + /** + * \name Token + * \{ + */ + PID_OUT = 0xE1, + PID_IN = 0x69, + PID_SOF = 0xA5, + PID_SETUP = 0x2D, + /** + * \} + */ + + /** + * \name Data + * \{ + */ + PID_DATA0 = 0xC3, + PID_DATA1 = 0x4B, + PID_DATA2 = 0x87, // USB2 only + PID_MDATA = 0x0F, // USB2 only + /** + * \} + */ + + /** + * \name Handshake + * \{ + */ + PID_ACK = 0xD2, + PID_NAK = 0x5A, + PID_STALL = 0x1E, + PID_NYET = 0x96, + /** + * \} + */ + + /** + * \name Special + * \{ + */ + PID_PRE = 0x3C, PID_ERR = 0x3C, + PID_SPLIT = 0x78, + PID_PING = 0xB4, + PID_RESVD = 0xF0, + /** + * \} + */ +}; + +// === FUNCTIONS === +/** + * \note 00101 - X^5+X^2+1 + */ +Uint8 USB_TokenCRC(void *Data, int len); +/** + * \note X^16 + X15 + X^2 + 1 + */ +Uint16 USB_TokenCRC(void *Data, int len); + // === STRUCTURES === /** * \brief Defines a USB Host Controller diff --git a/README b/README index 61e69d24..6890ba3c 100644 --- a/README +++ b/README @@ -40,5 +40,10 @@ DRIVERS defines what device drivers are to be included from the Kernel MODULES defines what modules should be statically linked with the kernel (see /Modules for a list) -Finally set the source root directory (ACESSDIR) and the destination - directory (DISTROOT) then call make in the source root. +Set the source root directory (ACESSDIR) and the destination directory + (DISTROOT). + +Now you can compile the kernel and usermode applications by calling make + in the source root. + + diff --git a/Usermode/Libraries/libc.so_src/lib.h b/Usermode/Libraries/libc.so_src/lib.h index 49c5eb4c..9f773dce 100644 --- a/Usermode/Libraries/libc.so_src/lib.h +++ b/Usermode/Libraries/libc.so_src/lib.h @@ -1,11 +1,13 @@ /* -AcessOS Basic Lib C - -lib.h + * Acess2 Basic Lib C + * lib.h */ #ifndef _LIB_H #define _LIB_H +#include +#include + #define BUILD_SO 1 #if defined(BUILD_DLL) @@ -18,4 +20,12 @@ lib.h extern void *memcpy(void *dest, const void *src, size_t n); +typedef struct sCPUID tCPUID; + +struct sCPUID +{ + uint8_t SSE; + uint8_t SSE2; +}; + #endif diff --git a/Usermode/Libraries/libc.so_src/stub.c b/Usermode/Libraries/libc.so_src/stub.c index a10d9d11..0233b977 100644 --- a/Usermode/Libraries/libc.so_src/stub.c +++ b/Usermode/Libraries/libc.so_src/stub.c @@ -2,13 +2,21 @@ * AcessOS Basic C Library */ #include "stdio_int.h" +#include "lib.h" +// === PROTOTYPES === +static void cpuid(uint32_t Num, uint32_t *EAX, uint32_t *EBX, uint32_t *EDX, uint32_t *ECX); + +// === GLOBALS === extern char **_envp; extern struct sFILE _iob[]; extern struct sFILE *stdin; extern struct sFILE *stdout; extern struct sFILE *stderr; +// --- CPU Features --- +tCPUID gCPU_Features; +// === CODE === /** * \fn int SoMain() * \brief Stub Entrypoint @@ -30,5 +38,34 @@ int SoMain(unsigned int BaseAddress, int argc, char **argv, char **envp) stderr = &_iob[2]; stderr->FD = 2; stderr->Flags = FILE_FLAG_MODE_WRITE; + /* + { + uint32_t ecx, edx; + cpuid(1, NULL, NULL, &edx, &ecx); + gCPU_Features.SSE = edx & (1 << 25); // SSE + gCPU_Features.SSE2 = edx & (1 << 26); // SSE2 + } + */ + return 1; } + + +/** + * \brief Call the CPUID opcode + */ +static void cpuid(uint32_t Num, uint32_t *EAX, uint32_t *EBX, uint32_t *EDX, uint32_t *ECX) +{ + uint32_t eax, ebx, edx, ecx; + + __asm__ __volatile__ ( + "cpuid" + : "=a"(eax), "=c"(ecx), "=d"(edx) + : "a"(Num) + ); + + if(EAX) *EAX = eax; + if(EBX) *EBX = ebx; + if(EDX) *EDX = edx; + if(ECX) *ECX = ecx; +} diff --git a/Usermode/include/acess/devices.h b/Usermode/include/acess/devices.h index 1039430e..bfbb6256 100644 --- a/Usermode/include/acess/devices.h +++ b/Usermode/include/acess/devices.h @@ -44,4 +44,7 @@ enum eDrv_Mouse { MSE_IOCTL_MAX_Y }; +// === Terminal === +#include "devices/terminal.h" + #endif diff --git a/Usermode/include/acess/devices/terminal.h b/Usermode/include/acess/devices/terminal.h new file mode 100644 index 00000000..473271ca --- /dev/null +++ b/Usermode/include/acess/devices/terminal.h @@ -0,0 +1,58 @@ +/** + * \file devices/terminal.h + */ +#ifndef _SYS_DEVICES_TERMINAL_H +#define _SYS_DEVICES_TERMINAL_H + + +enum eDrv_Terminal { + TERM_IOCTL_MODETYPE = 4, + TERM_IOCTL_WIDTH, + TERM_IOCTL_HEIGHT, + TERM_IOCTL_QUERYMODE +}; + + +struct sTerm_IOCtl_Mode +{ + short ID; //!< Zero Based index of mode + short DriverID; //!< Driver's ID number (from ::tVideo_IOCtl_Mode) + Uint16 Height; //!< Height + Uint16 Width; //!< Width + Uint8 Depth; //!< Bits per cell + struct { + unsigned bText: 1; //!< Text Mode marker + unsigned unused: 7; + }; +}; + +/** + * \brief Terminal Modes + */ +enum eTplTerminal_Modes { + /** + * \brief UTF-8 Text Mode + * Any writes to the terminal file are treated as UTF-8 encoded + * strings and reads will also return UTF-8 strings. + */ + TERM_MODE_TEXT, + + /** + * \brief 32bpp Framebuffer + * Writes to the terminal file will write to the framebuffer. + * Reads will return UTF-32 characters + */ + TERM_MODE_FB, + + /** + * \brief OpenGL 2D/3D + * Writes to the terminal file will send 3D commands + * Reads will return UTF-32 characters + * \note May or may not stay in the spec + */ + TERM_MODE_OPENGL, + + NUM_TERM_MODES +}; + +#endif -- 2.20.1