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
__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
}
#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
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 );
}
Uint8 *VT_Font_GetChar(Uint32 Codepoint);
// === GLOBALS ===
-int giVT_CharWidth = FONT_WIDTH;
+int giVT_CharWidth = FONT_WIDTH+1;
int giVT_CharHeight = FONT_HEIGHT;
// === CODE ===
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;
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);
for( i = 0; i < giNumBuiltinModules; i++ )
{
if( baIsLoaded[i] ) continue; // Ignore already loaded modules
+
+ deps = gKernelModules[i].Dependencies;
if( deps )
{
}
// `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;
+++ /dev/null
-/*\r
- * Acess OS\r
- * Ext2 Driver Version 1\r
- */\r
-/**\r
- * \file fs/ext2.c\r
- * \brief Second Extended Filesystem Driver\r
- * \todo Implement file full write support\r
- */\r
-#define DEBUG 1\r
-#define VERBOSE 0\r
-#include <common.h>\r
-#include <vfs.h>\r
-#include <modules.h>\r
-#include "fs_ext2.h"\r
-\r
-#define EXT2_UPDATE_WRITEBACK 1\r
-\r
-// === STRUCTURES ===\r
-typedef struct {\r
- int FD;\r
- int CacheID;\r
- tVFS_Node RootNode;\r
- \r
- tExt2_SuperBlock SuperBlock;\r
- int BlockSize;\r
- \r
- int GroupCount;\r
- tExt2_Group Groups[];\r
-} tExt2_Disk;\r
-\r
-// === PROTOTYPES ===\r
- int Ext2_Install(char **Arguments);\r
-// Interface Functions\r
-tVFS_Node *Ext2_InitDevice(char *Device, char **Options);\r
-void Ext2_Unmount(tVFS_Node *Node);\r
-Uint64 Ext2_Read(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer);\r
-Uint64 Ext2_Write(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer);\r
-void Ext2_CloseFile(tVFS_Node *Node);\r
-char *Ext2_ReadDir(tVFS_Node *Node, int Pos);\r
-tVFS_Node *Ext2_FindDir(tVFS_Node *Node, char *FileName);\r
- int Ext2_MkNod(tVFS_Node *Node, char *Name, Uint Flags);\r
-// Internal Helpers\r
- int Ext2_int_GetInode(tVFS_Node *Node, tExt2_Inode *Inode);\r
-tVFS_Node *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeId, char *Name);\r
- int Ext2_int_ReadInode(tExt2_Disk *Disk, Uint InodeId, tExt2_Inode *Inode);\r
-Uint64 Ext2_int_GetBlockAddr(tExt2_Disk *Disk, Uint32 *Blocks, int BlockNum);\r
-Uint32 Ext2_int_AllocateInode(tExt2_Disk *Disk, Uint32 Parent);\r
-Uint32 Ext2_int_AllocateBlock(tExt2_Disk *Disk, Uint32 PrevBlock);\r
-void Ext2_int_UpdateSuperblock(tExt2_Disk *Disk);\r
-\r
-// === SEMI-GLOBALS ===\r
-MODULE_DEFINE(0, 0x5B /*v0.90*/, EXT2, Ext2_Install, NULL);\r
-tExt2_Disk gExt2_disks[6];\r
- int giExt2_count = 0;\r
-tVFS_Driver gExt2_FSInfo = {\r
- "ext2", 0, Ext2_InitDevice, Ext2_Unmount, NULL\r
- };\r
-\r
-// === CODE ===\r
-\r
-/**\r
- * \fn int Ext2_Install(char **Arguments)\r
- * \brief Install the Ext2 Filesystem Driver\r
- */\r
-int Ext2_Install(char **Arguments)\r
-{\r
- VFS_AddDriver( &gExt2_FSInfo );\r
- return 1;\r
-}\r
-\r
-/**\r
- \fn tVFS_Node *Ext2_InitDevice(char *Device, char **Options)\r
- \brief Initializes a device to be read by by the driver\r
- \param Device String - Device to read from\r
- \param Options NULL Terminated array of option strings\r
- \return Root Node\r
-*/\r
-tVFS_Node *Ext2_InitDevice(char *Device, char **Options)\r
-{\r
- tExt2_Disk *disk;\r
- int fd;\r
- int groupCount;\r
- tExt2_SuperBlock sb;\r
- tExt2_Inode inode;\r
- \r
- ENTER("sDevice pOptions", Device, Options);\r
- \r
- // Open Disk\r
- fd = VFS_Open(Device, VFS_OPENFLAG_READ|VFS_OPENFLAG_WRITE); //Open Device\r
- if(fd == -1) {\r
- Warning("[EXT2 ] Unable to open '%s'", Device);\r
- LEAVE('n');\r
- return NULL;\r
- }\r
- \r
- // Read Superblock at offset 1024\r
- VFS_ReadAt(fd, 1024, 1024, &sb); // Read Superblock\r
- \r
- // Sanity Check Magic value\r
- if(sb.s_magic != 0xEF53) {\r
- Warning("[EXT2 ] Volume '%s' is not an EXT2 volume", Device);\r
- VFS_Close(fd);\r
- LEAVE('n');\r
- return NULL;\r
- }\r
- \r
- // Get Group count\r
- groupCount = DivUp(sb.s_blocks_count, sb.s_blocks_per_group);\r
- LOG("groupCount = %i", groupCount);\r
- \r
- // Allocate Disk Information\r
- disk = malloc(sizeof(tExt2_Disk) + sizeof(tExt2_Group)*groupCount);\r
- if(!disk) {\r
- Warning("[EXT2 ] Unable to allocate disk structure");\r
- VFS_Close(fd);\r
- LEAVE('n');\r
- return NULL;\r
- }\r
- disk->FD = fd;\r
- memcpy(&disk->SuperBlock, &sb, 1024);\r
- disk->GroupCount = groupCount;\r
- \r
- // Get an inode cache handle\r
- disk->CacheID = Inode_GetHandle();\r
- \r
- // Get Block Size\r
- LOG("s_log_block_size = 0x%x", sb.s_log_block_size);\r
- disk->BlockSize = 1024 << sb.s_log_block_size;\r
- \r
- // Read Group Information\r
- VFS_ReadAt(\r
- disk->FD,\r
- sb.s_first_data_block * disk->BlockSize + 1024,\r
- sizeof(tExt2_Group)*groupCount,\r
- disk->Groups\r
- );\r
- \r
- #if VERBOSE\r
- LOG("Block Group 0");\r
- LOG(".bg_block_bitmap = 0x%x", disk->Groups[0].bg_block_bitmap);\r
- LOG(".bg_inode_bitmap = 0x%x", disk->Groups[0].bg_inode_bitmap);\r
- LOG(".bg_inode_table = 0x%x", disk->Groups[0].bg_inode_table);\r
- LOG("Block Group 1");\r
- LOG(".bg_block_bitmap = 0x%x", disk->Groups[1].bg_block_bitmap);\r
- LOG(".bg_inode_bitmap = 0x%x", disk->Groups[1].bg_inode_bitmap);\r
- LOG(".bg_inode_table = 0x%x", disk->Groups[1].bg_inode_table);\r
- #endif\r
- \r
- // Get root Inode\r
- Ext2_int_ReadInode(disk, 2, &inode);\r
- \r
- // Create Root Node\r
- memset(&disk->RootNode, 0, sizeof(tVFS_Node));\r
- disk->RootNode.Inode = 2; // Root inode ID\r
- disk->RootNode.ImplPtr = disk; // Save disk pointer\r
- disk->RootNode.Size = -1; // Fill in later (on readdir)\r
- disk->RootNode.Flags = VFS_FFLAG_DIRECTORY;\r
- \r
- disk->RootNode.ReadDir = Ext2_ReadDir;\r
- disk->RootNode.FindDir = Ext2_FindDir;\r
- //disk->RootNode.Relink = Ext2_Relink;\r
- \r
- // Complete root node\r
- disk->RootNode.UID = inode.i_uid;\r
- disk->RootNode.GID = inode.i_gid;\r
- disk->RootNode.NumACLs = 1;\r
- disk->RootNode.ACLs = &gVFS_ACL_EveryoneRW;\r
- \r
- #if DEBUG\r
- LOG("inode.i_size = 0x%x", inode.i_size);\r
- LOG("inode.i_block[0] = 0x%x", inode.i_block[0]);\r
- #endif\r
- \r
- LEAVE('p', &disk->RootNode);\r
- return &disk->RootNode;\r
-}\r
-\r
-/**\r
- * \fn void Ext2_Unmount(tVFS_Node *Node)\r
- * \brief Close a mounted device\r
- */\r
-void Ext2_Unmount(tVFS_Node *Node)\r
-{\r
- tExt2_Disk *disk = Node->ImplPtr;\r
- \r
- VFS_Close( disk->FD );\r
- Inode_ClearCache( disk->CacheID );\r
- memset(disk, 0, sizeof(tExt2_Disk)+disk->GroupCount*sizeof(tExt2_Group));\r
- free(disk);\r
-}\r
-\r
-/**\r
- * \fn Uint64 Ext2_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)\r
- * \brief Read from a file\r
- */\r
-Uint64 Ext2_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)\r
-{\r
- tExt2_Disk *disk = Node->ImplPtr;\r
- tExt2_Inode inode;\r
- Uint64 base;\r
- Uint block;\r
- Uint64 remLen;\r
- \r
- ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer);\r
- \r
- // Get Inode\r
- Ext2_int_GetInode(Node, &inode);\r
- \r
- // Sanity Checks\r
- if(Offset >= inode.i_size) {\r
- LEAVE('i', 0);\r
- return 0;\r
- }\r
- if(Offset + Length > inode.i_size)\r
- Length = inode.i_size - Offset;\r
- \r
- block = Offset / disk->BlockSize;\r
- Offset = Offset / disk->BlockSize;\r
- base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);\r
- if(base == 0) {\r
- Warning("[EXT2 ] NULL Block Detected in INode 0x%llx", Node->Inode);\r
- LEAVE('i', 0);\r
- return 0;\r
- }\r
- \r
- // Read only block\r
- if(Length <= disk->BlockSize - Offset)\r
- {\r
- VFS_ReadAt( disk->FD, base+Offset, Length, Buffer);\r
- LEAVE('X', Length);\r
- return Length;\r
- }\r
- \r
- // Read first block\r
- remLen = Length;\r
- VFS_ReadAt( disk->FD, base + Offset, disk->BlockSize - Offset, Buffer);\r
- remLen -= disk->BlockSize - Offset;\r
- Buffer += disk->BlockSize - Offset;\r
- block ++;\r
- \r
- // Read middle blocks\r
- while(remLen > disk->BlockSize)\r
- {\r
- base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);\r
- if(base == 0) {\r
- Warning("[EXT2 ] NULL Block Detected in INode 0x%llx", Node->Inode);\r
- LEAVE('i', 0);\r
- return 0;\r
- }\r
- VFS_ReadAt( disk->FD, base, disk->BlockSize, Buffer);\r
- Buffer += disk->BlockSize;\r
- remLen -= disk->BlockSize;\r
- block ++;\r
- }\r
- \r
- // Read last block\r
- base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);\r
- VFS_ReadAt( disk->FD, base, remLen, Buffer);\r
- \r
- LEAVE('X', Length);\r
- return Length;\r
-}\r
-\r
-/**\r
- * \fn Uint64 Ext2_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)\r
- * \brief Write to a file\r
- */\r
-Uint64 Ext2_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)\r
-{\r
- tExt2_Disk *disk = Node->ImplPtr;\r
- tExt2_Inode inode;\r
- Uint64 base;\r
- Uint64 retLen;\r
- Uint block;\r
- Uint64 allocSize;\r
- int bNewBlocks = 0;\r
- \r
- Debug_HexDump("Ext2_Write", Buffer, Length);\r
- \r
- Ext2_int_GetInode(Node, &inode);\r
- \r
- // Get the ammount of space already allocated\r
- // - Round size up to block size\r
- // - block size is a power of two, so this will work\r
- allocSize = (inode.i_size + disk->BlockSize) & ~(disk->BlockSize-1);\r
- \r
- // Are we writing to inside the allocated space?\r
- if( Offset < allocSize )\r
- {\r
- // Will we go out of it?\r
- if(Offset + Length > allocSize) {\r
- bNewBlocks = 1;\r
- retLen = allocSize - Offset;\r
- } else\r
- retLen = Length;\r
- \r
- // Within the allocated space\r
- block = Offset / disk->BlockSize;\r
- Offset %= disk->BlockSize;\r
- base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);\r
- \r
- // Write only block (if only one)\r
- if(Offset + retLen <= disk->BlockSize) {\r
- VFS_WriteAt(disk->FD, base+Offset, retLen, Buffer);\r
- if(!bNewBlocks) return Length;\r
- goto addBlocks; // Ugh! A goto, but it seems unavoidable\r
- }\r
- \r
- // Write First Block\r
- VFS_WriteAt(disk->FD, base+Offset, disk->BlockSize-Offset, Buffer);\r
- Buffer += disk->BlockSize-Offset;\r
- retLen -= disk->BlockSize-Offset;\r
- block ++;\r
- \r
- // Write middle blocks\r
- while(retLen > disk->BlockSize)\r
- {\r
- base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);\r
- VFS_WriteAt(disk->FD, base, disk->BlockSize, Buffer);\r
- Buffer += disk->BlockSize;\r
- retLen -= disk->BlockSize;\r
- block ++;\r
- }\r
- \r
- // Write last block\r
- base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);\r
- VFS_WriteAt(disk->FD, base, retLen, Buffer);\r
- if(!bNewBlocks) return Length; // Writing in only allocated space\r
- }\r
- \r
-addBlocks:\r
- ///\todo Implement block allocation\r
- Warning("[EXT2] File extending is not yet supported");\r
- \r
- return 0;\r
-}\r
-\r
-/**\r
- * \fn void Ext2_CloseFile(tVFS_Node *Node)\r
- * \brief Close a file (Remove it from the cache)\r
- */\r
-void Ext2_CloseFile(tVFS_Node *Node)\r
-{\r
- tExt2_Disk *disk = Node->ImplPtr;\r
- Inode_UncacheNode(disk->CacheID, Node->Inode);\r
- return ;\r
-}\r
-\r
-/**\r
- \fn char *Ext2_ReadDir(tVFS_Node *Node, int Pos)\r
- \brief Reads a directory entry\r
-*/\r
-char *Ext2_ReadDir(tVFS_Node *Node, int Pos)\r
-{\r
- tExt2_Inode inode;\r
- char namebuf[EXT2_NAME_LEN+1];\r
- tExt2_DirEnt dirent;\r
- Uint64 Base; // Block's Base Address\r
- int block = 0, ofs = 0;\r
- int entNum = 0;\r
- tExt2_Disk *disk = Node->ImplPtr;\r
- Uint size;\r
- \r
- ENTER("pNode iPos", Node, Pos);\r
- \r
- // Read directory's inode\r
- Ext2_int_GetInode(Node, &inode);\r
- size = inode.i_size;\r
- \r
- LOG("inode.i_block[0] = 0x%x", inode.i_block[0]);\r
- \r
- // Find Entry\r
- // Get First Block\r
- // - Do this ourselves as it is a simple operation\r
- Base = inode.i_block[0] * disk->BlockSize;\r
- while(Pos -- && size > 0)\r
- {\r
- VFS_ReadAt( disk->FD, Base+ofs, sizeof(tExt2_DirEnt), &dirent);\r
- ofs += dirent.rec_len;\r
- size -= dirent.rec_len;\r
- entNum ++;\r
- \r
- if(ofs >= disk->BlockSize) {\r
- block ++;\r
- if( ofs > disk->BlockSize ) {\r
- Warning("[EXT2] Directory Entry %i of inode %i extends over a block boundary, ignoring",\r
- entNum-1, Node->Inode);\r
- }\r
- ofs = 0;\r
- Base = Ext2_int_GetBlockAddr( disk, inode.i_block, block );\r
- }\r
- }\r
- \r
- // Check for the end of the list\r
- if(size <= 0) {\r
- LEAVE('n');\r
- return NULL;\r
- }\r
- \r
- // Read Entry\r
- VFS_ReadAt( disk->FD, Base+ofs, sizeof(tExt2_DirEnt), &dirent );\r
- //LOG("dirent.inode = %i", dirent.inode);\r
- //LOG("dirent.rec_len = %i", dirent.rec_len);\r
- //LOG("dirent.name_len = %i", dirent.name_len);\r
- VFS_ReadAt( disk->FD, Base+ofs+sizeof(tExt2_DirEnt), dirent.name_len, namebuf );\r
- namebuf[ dirent.name_len ] = '\0'; // Cap off string\r
- \r
- \r
- // Ignore . and .. (these are done in the VFS)\r
- if( (namebuf[0] == '.' && namebuf[1] == '\0')\r
- || (namebuf[0] == '.' && namebuf[1] == '.' && namebuf[2]=='\0')) {\r
- LEAVE('p', VFS_SKIP);\r
- return VFS_SKIP; // Skip\r
- }\r
- \r
- LEAVE('s', namebuf);\r
- // Create new node\r
- return strdup(namebuf);\r
-}\r
-\r
-/**\r
- \fn tVFS_Node *Ext2_FindDir(tVFS_Node *node, char *filename)\r
- \brief Gets information about a file\r
- \param node vfs node - Parent Node\r
- \param filename String - Name of file\r
- \return VFS Node of file\r
-*/\r
-tVFS_Node *Ext2_FindDir(tVFS_Node *Node, char *Filename)\r
-{\r
- tExt2_Disk *disk = Node->ImplPtr;\r
- tExt2_Inode inode;\r
- char namebuf[EXT2_NAME_LEN+1];\r
- tExt2_DirEnt dirent;\r
- Uint64 Base; // Block's Base Address\r
- int block = 0, ofs = 0;\r
- int entNum = 0;\r
- Uint size;\r
- \r
- // Read directory's inode\r
- Ext2_int_GetInode(Node, &inode);\r
- size = inode.i_size;\r
- \r
- // Get First Block\r
- // - Do this ourselves as it is a simple operation\r
- Base = inode.i_block[0] * disk->BlockSize;\r
- // Find File\r
- while(size > 0)\r
- {\r
- VFS_ReadAt( disk->FD, Base+ofs, sizeof(tExt2_DirEnt), &dirent);\r
- VFS_ReadAt( disk->FD, Base+ofs+sizeof(tExt2_DirEnt), dirent.name_len, namebuf );\r
- namebuf[ dirent.name_len ] = '\0'; // Cap off string\r
- // If it matches, create a node and return it\r
- if(strcmp(namebuf, Filename) == 0)\r
- return Ext2_int_CreateNode( disk, dirent.inode, namebuf );\r
- // Increment pointers\r
- ofs += dirent.rec_len;\r
- size -= dirent.rec_len;\r
- entNum ++;\r
- \r
- // Check for end of block\r
- if(ofs >= disk->BlockSize) {\r
- block ++;\r
- if( ofs > disk->BlockSize ) {\r
- Warning("[EXT2 ] Directory Entry %i of inode %i extends over a block boundary, ignoring",\r
- entNum-1, Node->Inode);\r
- }\r
- ofs = 0;\r
- Base = Ext2_int_GetBlockAddr( disk, inode.i_block, block );\r
- }\r
- }\r
- \r
- return NULL;\r
-}\r
-\r
-/**\r
- * \fn int Ext2_MkNod(tVFS_Node *Parent, char *Name, Uint Flags)\r
- * \brief Create a new node\r
- */\r
-int Ext2_MkNod(tVFS_Node *Parent, char *Name, Uint Flags)\r
-{\r
- return 0;\r
-}\r
-\r
-//==================================\r
-//= INTERNAL FUNCTIONS =\r
-//==================================\r
-\r
-\r
-/**\r
- * \fn int Ext2_int_GetInode(tVFS_Node *Node, tExt2_Inode *Inode)\r
- * \brief Gets the inode descriptor for a node\r
- * \param Node node to get the Inode of\r
- * \param Inode Destination\r
- */\r
-int Ext2_int_GetInode(tVFS_Node *Node, tExt2_Inode *Inode)\r
-{\r
- return Ext2_int_ReadInode(Node->ImplPtr, Node->Inode, Inode);\r
-}\r
-\r
-/**\r
- * \fn vfs_node *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeID, char *Name)\r
- * \brief Create a new VFS Node\r
- */\r
-tVFS_Node *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeID, char *Name)\r
-{\r
- tExt2_Inode inode;\r
- tVFS_Node retNode;\r
- tVFS_Node *tmpNode;\r
- \r
- if( !Ext2_int_ReadInode(Disk, InodeID, &inode) )\r
- return NULL;\r
- \r
- if( (tmpNode = Inode_GetCache(Disk->CacheID, InodeID)) )\r
- return tmpNode;\r
- \r
- \r
- // Set identifiers\r
- retNode.Inode = InodeID;\r
- retNode.ImplPtr = Disk;\r
- \r
- // Set file length\r
- retNode.Size = inode.i_size;\r
- \r
- // Set Access Permissions\r
- retNode.UID = inode.i_uid;\r
- retNode.GID = inode.i_gid;\r
- retNode.NumACLs = 3;\r
- retNode.ACLs = VFS_UnixToAcessACL(inode.i_mode & 0777, inode.i_uid, inode.i_gid);\r
- \r
- // Set Function Pointers\r
- retNode.Read = Ext2_Read;\r
- retNode.Write = Ext2_Write;\r
- retNode.Close = Ext2_CloseFile;\r
- \r
- switch(inode.i_mode & EXT2_S_IFMT)\r
- {\r
- // Symbolic Link\r
- case EXT2_S_IFLNK:\r
- retNode.Flags = VFS_FFLAG_SYMLINK;\r
- break;\r
- // Regular File\r
- case EXT2_S_IFREG:\r
- retNode.Flags = 0;\r
- retNode.Size |= (Uint64)inode.i_dir_acl << 32;\r
- break;\r
- // Directory\r
- case EXT2_S_IFDIR:\r
- retNode.ReadDir = Ext2_ReadDir;\r
- retNode.FindDir = Ext2_FindDir;\r
- retNode.MkNod = Ext2_MkNod;\r
- //retNode.Relink = Ext2_Relink;\r
- retNode.Flags = VFS_FFLAG_DIRECTORY;\r
- break;\r
- // Unknown, Write protect and hide it to be safe \r
- default:\r
- retNode.Flags = VFS_FFLAG_READONLY;//|VFS_FFLAG_HIDDEN;\r
- break;\r
- }\r
- \r
- // Check if the file should be hidden\r
- //if(Name[0] == '.') retNode.Flags |= VFS_FFLAG_HIDDEN;\r
- \r
- // Set Timestamps\r
- retNode.ATime = now();\r
- retNode.MTime = inode.i_mtime * 1000;\r
- retNode.CTime = inode.i_ctime * 1000;\r
- \r
- // Save in node cache and return saved node\r
- return Inode_CacheNode(Disk->CacheID, &retNode);\r
-}\r
-\r
-/**\r
- * \fn int Ext2_int_ReadInode(tExt2_Disk *Disk, Uint InodeId, tExt2_Inode *Inode)\r
- * \brief Read an inode into memory\r
- */\r
-int Ext2_int_ReadInode(tExt2_Disk *Disk, Uint InodeId, tExt2_Inode *Inode)\r
-{\r
- int group, subId;\r
- \r
- //LogF("Ext2_int_ReadInode: (Disk=%p, InodeId=%i, Inode=%p)", Disk, InodeId, Inode);\r
- //ENTER("pDisk iInodeId pInode", Disk, InodeId, Inode);\r
- \r
- if(InodeId == 0) return 0;\r
- \r
- InodeId --; // Inodes are numbered starting at 1\r
- \r
- group = InodeId / Disk->SuperBlock.s_inodes_per_group;\r
- subId = InodeId % Disk->SuperBlock.s_inodes_per_group;\r
- \r
- //LOG("group=%i, subId = %i", group, subId);\r
- \r
- // Read Inode\r
- VFS_ReadAt(Disk->FD,\r
- Disk->Groups[group].bg_inode_table * Disk->BlockSize + sizeof(tExt2_Inode)*subId,\r
- sizeof(tExt2_Inode),\r
- Inode);\r
- return 1;\r
-}\r
-\r
-/**\r
- * \fn Uint64 Ext2_int_GetBlockAddr(tExt2_Disk *Disk, Uint32 *Blocks, int BlockNum)\r
- * \brief Get the address of a block from an inode's list\r
- * \param Disk Disk information structure\r
- * \param Blocks Pointer to an inode's block list\r
- * \param BlockNum Block index in list\r
- */\r
-Uint64 Ext2_int_GetBlockAddr(tExt2_Disk *Disk, Uint32 *Blocks, int BlockNum)\r
-{\r
- Uint32 *iBlocks;\r
- // Direct Blocks\r
- if(BlockNum < 12)\r
- return (Uint64)Blocks[BlockNum] * Disk->BlockSize;\r
- \r
- // Single Indirect Blocks\r
- iBlocks = malloc( Disk->BlockSize );\r
- VFS_ReadAt(Disk->FD, (Uint64)Blocks[12]*Disk->BlockSize, Disk->BlockSize, iBlocks);\r
- \r
- BlockNum -= 12;\r
- if(BlockNum < 256) {\r
- BlockNum = iBlocks[BlockNum];\r
- free(iBlocks);\r
- return (Uint64)BlockNum * Disk->BlockSize;\r
- }\r
- \r
- // Double Indirect Blocks\r
- if(BlockNum < 256*256)\r
- {\r
- VFS_ReadAt(Disk->FD, (Uint64)Blocks[13]*Disk->BlockSize, Disk->BlockSize, iBlocks);\r
- VFS_ReadAt(Disk->FD, (Uint64)iBlocks[BlockNum/256]*Disk->BlockSize, Disk->BlockSize, iBlocks);\r
- BlockNum = iBlocks[BlockNum%256];\r
- free(iBlocks);\r
- return (Uint64)BlockNum * Disk->BlockSize;\r
- }\r
- // Triple Indirect Blocks\r
- VFS_ReadAt(Disk->FD, (Uint64)Blocks[14]*Disk->BlockSize, Disk->BlockSize, iBlocks);\r
- VFS_ReadAt(Disk->FD, (Uint64)iBlocks[BlockNum/(256*256)]*Disk->BlockSize, Disk->BlockSize, iBlocks);\r
- VFS_ReadAt(Disk->FD, (Uint64)iBlocks[(BlockNum/256)%256]*Disk->BlockSize, Disk->BlockSize, iBlocks);\r
- BlockNum = iBlocks[BlockNum%256];\r
- free(iBlocks);\r
- return (Uint64)BlockNum * Disk->BlockSize;\r
-}\r
-\r
-/**\r
- * \fn Uint32 Ext2_int_AllocateInode(tExt2_Disk *Disk, Uint32 Parent)\r
- * \brief Allocate an inode (from the current group preferably)\r
- * \param Disk EXT2 Disk Information Structure\r
- * \param Parent Inode ID of the parent (used to locate the child nearby)\r
- */\r
-Uint32 Ext2_int_AllocateInode(tExt2_Disk *Disk, Uint32 Parent)\r
-{\r
-// Uint block = (Parent - 1) / Disk->SuperBlock.s_inodes_per_group;\r
- return 0;\r
-}\r
-\r
-/**\r
- * \fn Uint32 Ext2_int_AllocateBlock(tExt2_Disk *Disk, Uint32 PrevBlock)\r
- * \brief Allocate a block from the best possible location\r
- * \param Disk EXT2 Disk Information Structure\r
- * \param PrevBlock Previous block ID in the file\r
- */\r
-Uint32 Ext2_int_AllocateBlock(tExt2_Disk *Disk, Uint32 PrevBlock)\r
-{\r
- int bpg = Disk->SuperBlock.s_blocks_per_group;\r
- Uint blockgroup = PrevBlock / bpg;\r
- Uint bitmap[Disk->BlockSize/sizeof(Uint)];\r
- Uint bitsperblock = 8*Disk->BlockSize;\r
- int i, j = 0;\r
- Uint block;\r
- \r
- // Are there any free blocks?\r
- if(Disk->SuperBlock.s_free_blocks_count == 0) return 0;\r
- \r
- if(Disk->Groups[blockgroup].bg_free_blocks_count > 0)\r
- {\r
- // Search block group's bitmap\r
- for(i = 0; i < bpg; i++)\r
- {\r
- // Get the block in the bitmap block\r
- j = i & (bitsperblock-1);\r
- \r
- // Read in if needed\r
- if(j == 0) {\r
- VFS_ReadAt(\r
- Disk->FD,\r
- (Uint64)Disk->Groups[blockgroup].bg_block_bitmap + i / bitsperblock,\r
- Disk->BlockSize,\r
- bitmap\r
- );\r
- }\r
- \r
- // Fast Check\r
- if( bitmap[j/32] == -1 ) {\r
- j = (j + 31) & ~31;\r
- continue;\r
- }\r
- \r
- // Is the bit set?\r
- if( bitmap[j/32] & (1 << (j%32)) )\r
- continue;\r
- \r
- // Ooh! We found one\r
- break;\r
- }\r
- if( i < bpg ) {\r
- Warning("[EXT2 ] Inconsistency detected, Group Free Block count is non-zero when no free blocks exist");\r
- goto checkAll; // Search the entire filesystem for a free block\r
- // Goto needed for neatness\r
- }\r
- \r
- // Mark as used\r
- bitmap[j/32] |= (1 << (j%32));\r
- VFS_WriteAt(\r
- Disk->FD,\r
- (Uint64)Disk->Groups[blockgroup].bg_block_bitmap + i / bitsperblock,\r
- Disk->BlockSize,\r
- bitmap\r
- );\r
- block = i;\r
- Disk->Groups[blockgroup].bg_free_blocks_count --;\r
- }\r
- else\r
- {\r
- checkAll:\r
- Warning("[EXT2 ] TODO - Implement using blocks outside the current block group");\r
- return 0;\r
- }\r
- \r
- // Reduce global count\r
- Disk->SuperBlock.s_free_blocks_count --;\r
- #if EXT2_UPDATE_WRITEBACK\r
- Ext2_int_UpdateSuperblock(Disk);\r
- #endif\r
- \r
- return block;\r
-}\r
-\r
-/**\r
- * \fn void Ext2_int_UpdateSuperblock(tExt2_Disk *Disk)\r
- */\r
-void Ext2_int_UpdateSuperblock(tExt2_Disk *Disk)\r
-{\r
- VFS_WriteAt(Disk->FD, 1024, 1024, &Disk->SuperBlock);\r
-}\r
+++ /dev/null
-/**\r
- * Acess2\r
- * \file fs_ext2.h\r
- * \brief EXT2 Filesystem Driver\r
- */\r
-\r
-/**\r
- \name Inode Flag Values\r
- \{\r
-*/\r
-#define EXT2_S_IFMT 0xF000 //!< Format Mask\r
-#define EXT2_S_IFSOCK 0xC000 //!< Socket\r
-#define EXT2_S_IFLNK 0xA000 //!< Symbolic Link\r
-#define EXT2_S_IFREG 0x8000 //!< Regular File\r
-#define EXT2_S_IFBLK 0x6000 //!< Block Device\r
-#define EXT2_S_IFDIR 0x4000 //!< Directory\r
-#define EXT2_S_IFCHR 0x2000 //!< Character Device\r
-#define EXT2_S_IFIFO 0x1000 //!< FIFO\r
-#define EXT2_S_ISUID 0x0800 //!< SUID\r
-#define EXT2_S_ISGID 0x0400 //!< SGID\r
-#define EXT2_S_ISVTX 0x0200 //!< sticky bit\r
-#define EXT2_S_IRWXU 0700 //!< user access rights mask\r
-#define EXT2_S_IRUSR 0400 //!< Owner Read\r
-#define EXT2_S_IWUSR 0200 //!< Owner Write\r
-#define EXT2_S_IXUSR 0100 //!< Owner Execute\r
-#define EXT2_S_IRWXG 0070 //!< Group Access rights mask\r
-#define EXT2_S_IRGRP 0040 //!< Group Read\r
-#define EXT2_S_IWGRP 0020 //!< Group Write\r
-#define EXT2_S_IXGRP 0010 //!< Group Execute\r
-#define EXT2_S_IRWXO 0007 //!< Global Access rights mask\r
-#define EXT2_S_IROTH 0004 //!< Global Read\r
-#define EXT2_S_IWOTH 0002 //!< Global Write\r
-#define EXT2_S_IXOTH 0001 //!< Global Execute\r
-//! \}\r
-\r
-#define EXT2_NAME_LEN 255 //!< Maximum Name Length\r
-\r
-// === TYPEDEFS ===\r
-typedef struct ext2_inode_s tExt2_Inode; //!< Inode Type\r
-typedef struct ext2_super_block_s tExt2_SuperBlock; //!< Superblock Type\r
-typedef struct ext2_group_desc_s tExt2_Group; //!< Group Descriptor Type\r
-typedef struct ext2_dir_entry_s tExt2_DirEnt; //!< Directory Entry Type\r
-\r
-// === STRUCTURES ===\r
-/**\r
- * \brief EXT2 Superblock Structure\r
- */\r
-struct ext2_super_block_s {\r
- Uint32 s_inodes_count; //!< Inodes count\r
- Uint32 s_blocks_count; //!< Blocks count\r
- Uint32 s_r_blocks_count; //!< Reserved blocks count\r
- Uint32 s_free_blocks_count; //!< Free blocks count\r
- Uint32 s_free_inodes_count; //!< Free inodes count\r
- Uint32 s_first_data_block; //!< First Data Block\r
- Uint32 s_log_block_size; //!< Block size\r
- Sint32 s_log_frag_size; //!< Fragment size\r
- Uint32 s_blocks_per_group; //!< Number Blocks per group\r
- Uint32 s_frags_per_group; //!< Number Fragments per group\r
- Uint32 s_inodes_per_group; //!< Number Inodes per group\r
- Uint32 s_mtime; //!< Mount time\r
- Uint32 s_wtime; //!< Write time\r
- Uint16 s_mnt_count; //!< Mount count\r
- Sint16 s_max_mnt_count; //!< Maximal mount count\r
- Uint16 s_magic; //!< Magic signature\r
- Uint16 s_state; //!< File system state\r
- Uint16 s_errors; //!< Behaviour when detecting errors\r
- Uint16 s_pad; //!< Padding\r
- Uint32 s_lastcheck; //!< time of last check\r
- Uint32 s_checkinterval; //!< max. time between checks\r
- Uint32 s_creator_os; //!< Formatting OS\r
- Uint32 s_rev_level; //!< Revision level\r
- Uint16 s_def_resuid; //!< Default uid for reserved blocks\r
- Uint16 s_def_resgid; //!< Default gid for reserved blocks\r
- Uint32 s_reserved[235]; //!< Padding to the end of the block\r
-};\r
-\r
-/**\r
- * \struct ext2_inode_s\r
- * \brief EXT2 Inode Definition\r
- */\r
-struct ext2_inode_s {\r
- Uint16 i_mode; //!< File mode\r
- Uint16 i_uid; //!< Owner Uid\r
- Uint32 i_size; //!< Size in bytes\r
- Uint32 i_atime; //!< Access time\r
- Uint32 i_ctime; //!< Creation time\r
- Uint32 i_mtime; //!< Modification time\r
- Uint32 i_dtime; //!< Deletion Time\r
- Uint16 i_gid; //!< Group Id\r
- Uint16 i_links_count; //!< Links count\r
- Uint32 i_blocks; //!< Blocks count\r
- Uint32 i_flags; //!< File flags\r
- union {\r
- Uint32 linux_reserved1; //!< Linux: Reserved\r
- Uint32 hurd_translator; //!< HURD: Translator\r
- Uint32 masix_reserved1; //!< Masix: Reserved\r
- } osd1; //!< OS dependent 1\r
- Uint32 i_block[15]; //!< Pointers to blocks\r
- Uint32 i_version; //!< File version (for NFS)\r
- Uint32 i_file_acl; //!< File ACL\r
- Uint32 i_dir_acl; //!< Directory ACL / Extended File Size\r
- Uint32 i_faddr; //!< Fragment address\r
- union {\r
- struct {\r
- Uint8 l_i_frag; //!< Fragment number\r
- Uint8 l_i_fsize; //!< Fragment size\r
- Uint16 i_pad1; //!< Padding\r
- Uint32 l_i_reserved2[2]; //!< Reserved\r
- } linux2;\r
- struct {\r
- Uint8 h_i_frag; //!< Fragment number\r
- Uint8 h_i_fsize; //!< Fragment size\r
- Uint16 h_i_mode_high; //!< Mode High Bits\r
- Uint16 h_i_uid_high; //!< UID High Bits\r
- Uint16 h_i_gid_high; //!< GID High Bits\r
- Uint32 h_i_author; //!< Creator ID\r
- } hurd2;\r
- struct {\r
- Uint8 m_i_frag; //!< Fragment number\r
- Uint8 m_i_fsize; //!< Fragment size\r
- Uint16 m_pad1; //!< Padding\r
- Uint32 m_i_reserved2[2]; //!< reserved\r
- } masix2;\r
- } osd2; //!< OS dependent 2\r
-};\r
-\r
-/**\r
- * \struct ext2_group_desc_s\r
- * \brief EXT2 Group Descriptor\r
- */\r
-struct ext2_group_desc_s {\r
- Uint32 bg_block_bitmap; //!< Blocks bitmap block\r
- Uint32 bg_inode_bitmap; //!< Inodes bitmap block\r
- Uint32 bg_inode_table; //!< Inodes table block\r
- Uint16 bg_free_blocks_count; //!< Free blocks count\r
- Uint16 bg_free_inodes_count; //!< Free inodes count\r
- Uint16 bg_used_dirs_count; //!< Directories count\r
- Uint16 bg_pad; //!< Padding\r
- Uint32 bg_reserved[3]; //!< Reserved\r
-};\r
-\r
-/**\r
- * \brief EXT2 Directory Entry\r
- * \note The name may take up less than 255 characters\r
- */\r
-struct ext2_dir_entry_s {\r
- Uint32 inode; //!< Inode number\r
- Uint16 rec_len; //!< Directory entry length\r
- Uint8 name_len; //!< Short Name Length\r
- Uint8 type; //!< File Type\r
- char name[]; //!< File name\r
-};\r
--- /dev/null
+#
+# 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
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
+++ /dev/null
-#
-#
-
-OBJ = bochsvbe.o
-NAME = BochsVBE
-
--include ../Makefile.tpl
+++ /dev/null
-/**\r
- * \file drv_bochsvbe.c\r
- * \brief BGA (Bochs Graphic Adapter) Driver\r
- * \note for Acess2\r
- * \warning This driver does NOT support the Bochs PCI VGA driver\r
-*/\r
-#define DEBUG 0\r
-#include <common.h>\r
-#include <errno.h>\r
-#include <modules.h>\r
-#include <vfs.h>\r
-#include <fs_devfs.h>\r
-#include <drv_pci.h>\r
-#include <tpl_drv_video.h>\r
-\r
-//#define INT static\r
-#define INT\r
-\r
-// === TYPEDEFS ===\r
-typedef struct {\r
- Uint16 width;\r
- Uint16 height;\r
- Uint16 bpp;\r
- Uint16 flags;\r
- Uint32 fbSize;\r
-} t_bga_mode;\r
-\r
-// === CONSTANTS ===\r
-enum eMode_Flags {\r
- MODEFLAG_TEXT = 1\r
-};\r
-#define BGA_LFB_MAXSIZE (1024*768*4)\r
-#define VBE_DISPI_BANK_ADDRESS 0xA0000\r
-#define VBE_DISPI_LFB_PHYSICAL_ADDRESS 0xE0000000\r
-#define VBE_DISPI_IOPORT_INDEX 0x01CE\r
-#define VBE_DISPI_IOPORT_DATA 0x01CF\r
-#define VBE_DISPI_DISABLED 0x00\r
-#define VBE_DISPI_ENABLED 0x01\r
-#define VBE_DISPI_LFB_ENABLED 0x40\r
-#define VBE_DISPI_NOCLEARMEM 0x80\r
-enum {\r
- VBE_DISPI_INDEX_ID,\r
- VBE_DISPI_INDEX_XRES,\r
- VBE_DISPI_INDEX_YRES,\r
- VBE_DISPI_INDEX_BPP,\r
- VBE_DISPI_INDEX_ENABLE,\r
- VBE_DISPI_INDEX_BANK,\r
- VBE_DISPI_INDEX_VIRT_WIDTH,\r
- VBE_DISPI_INDEX_VIRT_HEIGHT,\r
- VBE_DISPI_INDEX_X_OFFSET,\r
- VBE_DISPI_INDEX_Y_OFFSET\r
-};\r
-\r
-\r
-// === PROTOTYPES ===\r
-// Driver\r
- int BGA_Install(char **Arguments);\r
-void BGA_Uninstall();\r
-// Internal\r
-void BGA_int_WriteRegister(Uint16 reg, Uint16 value);\r
-Uint16 BGA_int_ReadRegister(Uint16 reg);\r
-void BGA_int_SetBank(Uint16 bank);\r
-void BGA_int_SetMode(Uint16 width, Uint16 height);\r
- int BGA_int_UpdateMode(int id);\r
- int BGA_int_FindMode(tVideo_IOCtl_Mode *info);\r
- int BGA_int_ModeInfo(tVideo_IOCtl_Mode *info);\r
- int BGA_int_MapFB(void *Dest);\r
-// Filesystem\r
-Uint64 BGA_Read(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer);\r
-Uint64 BGA_Write(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer);\r
- int BGA_Ioctl(tVFS_Node *node, int id, void *data);\r
-\r
-// === GLOBALS ===\r
-MODULE_DEFINE(0, 0x0032, BochsVBE, BGA_Install, NULL, NULL);\r
-tDevFS_Driver gBGA_DriverStruct = {\r
- NULL, "BochsGA",\r
- {\r
- .Read = BGA_Read,\r
- .Write = BGA_Write,\r
- .IOCtl = BGA_Ioctl\r
- }\r
-};\r
- int giBGA_CurrentMode = -1;\r
- int giBGA_DriverId = -1;\r
-Uint *gBGA_Framebuffer;\r
-t_bga_mode gBGA_Modes[] = {\r
- {},\r
- { 80,25, 12, MODEFLAG_TEXT, 80*25*8}, // 640 x 480\r
- {100,37, 12, MODEFLAG_TEXT, 100*37*8}, // 800 x 600\r
- {640,480,8, 0, 640*480},\r
- {640,480,32, 0, 640*480*4},\r
- {800,600,8, 0, 800*600},\r
- {800,600,32, 0, 800*600*4},\r
-};\r
-#define BGA_MODE_COUNT (sizeof(gBGA_Modes)/sizeof(gBGA_Modes[0]))\r
-\r
-// === CODE ===\r
-/**\r
- * \fn int BGA_Install(char **Arguments)\r
- */\r
-int BGA_Install(char **Arguments)\r
-{\r
- int bga_version = 0;\r
- \r
- // Check BGA Version\r
- bga_version = BGA_int_ReadRegister(VBE_DISPI_INDEX_ID);\r
- // NOTE: This driver was written for 0xB0C4, but they seem to be backwards compatable\r
- if(bga_version < 0xB0C4 || bga_version > 0xB0C5) {\r
- Warning("[BGA ] Bochs Adapter Version is not 0xB0C4 or 0xB0C5, instead 0x%x", bga_version);\r
- return 0;\r
- }\r
- \r
- // Install Device\r
- giBGA_DriverId = DevFS_AddDevice( &gBGA_DriverStruct );\r
- if(giBGA_DriverId == -1) {\r
- Warning("[BGA ] Unable to register with DevFS, maybe already loaded?");\r
- return 0;\r
- }\r
- \r
- // Map Framebuffer to hardware address\r
- gBGA_Framebuffer = (void *) MM_MapHWPage(VBE_DISPI_LFB_PHYSICAL_ADDRESS, 768); // 768 pages (3Mb)\r
- \r
- return 1;\r
-}\r
-\r
-/**\r
- * \fn void BGA_Uninstall()\r
- */\r
-void BGA_Uninstall()\r
-{\r
- //DevFS_DelDevice( giBGA_DriverId );\r
- MM_UnmapHWPage( VBE_DISPI_LFB_PHYSICAL_ADDRESS, 768 );\r
-}\r
-\r
-/**\r
- * \fn Uint64 BGA_Read(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer)\r
- * \brief Read from the framebuffer\r
- */\r
-Uint64 BGA_Read(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer)\r
-{\r
- // Check Mode\r
- if(giBGA_CurrentMode == -1) return -1;\r
- \r
- // Check Offset and Length against Framebuffer Size\r
- if(off+len > gBGA_Modes[giBGA_CurrentMode].fbSize)\r
- return -1;\r
- \r
- // Copy from Framebuffer\r
- memcpy(buffer, (void*)((Uint)gBGA_Framebuffer + (Uint)off), len);\r
- return len;\r
-}\r
-\r
-/**\r
- * \fn Uint64 BGA_Write(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer)\r
- * \brief Write to the framebuffer\r
- */\r
-Uint64 BGA_Write(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer)\r
-{ \r
- ENTER("xoff xlen", off, len);\r
- \r
- // Check Mode\r
- if(giBGA_CurrentMode == -1) {\r
- LEAVE('i', -1);\r
- return -1;\r
- }\r
- \r
- // Check Input against Frambuffer Size\r
- if(off+len > gBGA_Modes[giBGA_CurrentMode].fbSize) {\r
- LEAVE('i', -1);\r
- return -1;\r
- }\r
- \r
- // Text Mode\r
- if( gBGA_Modes[giBGA_CurrentMode].flags & MODEFLAG_TEXT )\r
- {\r
- tVT_Char *chars = buffer;\r
- int pitch = gBGA_Modes[giBGA_CurrentMode].width * giVT_CharWidth;\r
- Uint32 *dest;\r
- off /= sizeof(tVT_Char);\r
- dest = (void*)gBGA_Framebuffer;\r
- dest += (off / gBGA_Modes[giBGA_CurrentMode].width) * giVT_CharHeight * pitch;\r
- dest += (off % gBGA_Modes[giBGA_CurrentMode].width) * giVT_CharWidth;\r
- len /= sizeof(tVT_Char);\r
- while(len--)\r
- {\r
- VT_Font_Render(\r
- chars->Ch,\r
- dest, pitch,\r
- VT_Colour12to24(chars->BGCol),\r
- VT_Colour12to24(chars->FGCol)\r
- );\r
- dest += giVT_CharWidth;\r
- chars++;\r
- }\r
- }\r
- else\r
- {\r
- Uint8 *destBuf = (Uint8*) ((Uint)gBGA_Framebuffer + (Uint)off);\r
- \r
- LOG("buffer = %p\n", buffer);\r
- LOG("Updating Framebuffer (%p to %p)\n", \r
- destBuf, destBuf + (Uint)len);\r
- \r
- \r
- // Copy to Frambuffer\r
- memcpy(destBuf, buffer, len);\r
- \r
- LOG("BGA Framebuffer updated\n");\r
- }\r
- \r
- LEAVE('i', len);\r
- return len;\r
-}\r
-\r
-/**\r
- * \fn INT int BGA_Ioctl(tVFS_Node *node, int id, void *data)\r
- * \brief Handle messages to the device\r
- */\r
-INT int BGA_Ioctl(tVFS_Node *node, int id, void *data)\r
-{\r
- int ret = -2;\r
- ENTER("pNode iId pData", node, id, data);\r
- \r
- switch(id)\r
- {\r
- case DRV_IOCTL_TYPE:\r
- ret = DRV_TYPE_VIDEO;\r
- break;\r
- case DRV_IOCTL_IDENT:\r
- memcpy(data, "BGA1", 4);\r
- ret = 1;\r
- break;\r
- case DRV_IOCTL_VERSION:\r
- ret = 0x100;\r
- break;\r
- case DRV_IOCTL_LOOKUP: // TODO: Implement\r
- ret = 0;\r
- break;\r
- \r
- case VIDEO_IOCTL_SETMODE:\r
- ret = BGA_int_UpdateMode(*(int*)(data));\r
- break;\r
- \r
- case VIDEO_IOCTL_GETMODE:\r
- ret = giBGA_CurrentMode;\r
- break;\r
- \r
- case VIDEO_IOCTL_FINDMODE:\r
- ret = BGA_int_FindMode((tVideo_IOCtl_Mode*)data);\r
- break;\r
- \r
- case VIDEO_IOCTL_MODEINFO:\r
- ret = BGA_int_ModeInfo((tVideo_IOCtl_Mode*)data);\r
- break;\r
- \r
- // Request Access to LFB\r
- case VIDEO_IOCTL_REQLFB:\r
- ret = BGA_int_MapFB( *(void**)data );\r
- break;\r
- \r
- default:\r
- LEAVE('i', -2);\r
- return -2;\r
- }\r
- \r
- LEAVE('i', ret);\r
- return ret;\r
-}\r
-\r
-//== Internal Functions ==\r
-/**\r
- * \fn void BGA_int_WriteRegister(Uint16 reg, Uint16 value)\r
- * \brief Writes to a BGA register\r
- */\r
-void BGA_int_WriteRegister(Uint16 reg, Uint16 value)\r
-{\r
- outw(VBE_DISPI_IOPORT_INDEX, reg);\r
- outw(VBE_DISPI_IOPORT_DATA, value);\r
-}\r
-\r
-INT Uint16 BGA_int_ReadRegister(Uint16 reg)\r
-{\r
- outw(VBE_DISPI_IOPORT_INDEX, reg);\r
- return inw(VBE_DISPI_IOPORT_DATA);\r
-}\r
-\r
-#if 0\r
-INT void BGA_int_SetBank(Uint16 bank)\r
-{\r
- BGA_int_WriteRegister(VBE_DISPI_INDEX_BANK, bank);\r
-}\r
-#endif\r
-\r
-/**\r
- * \fn void BGA_int_SetMode(Uint16 width, Uint16 height, Uint16 bpp)\r
- * \brief Sets the video mode from the dimensions and bpp given\r
- */\r
-void BGA_int_SetMode(Uint16 width, Uint16 height)\r
-{\r
- ENTER("iwidth iheight ibpp", width, height, bpp);\r
- BGA_int_WriteRegister(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_DISABLED);\r
- BGA_int_WriteRegister(VBE_DISPI_INDEX_XRES, width);\r
- BGA_int_WriteRegister(VBE_DISPI_INDEX_YRES, height);\r
- BGA_int_WriteRegister(VBE_DISPI_INDEX_BPP, 32);\r
- BGA_int_WriteRegister(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_ENABLED | VBE_DISPI_NOCLEARMEM | VBE_DISPI_LFB_ENABLED);\r
- //BGA_int_WriteRegister(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_ENABLED | VBE_DISPI_NOCLEARMEM);\r
- LEAVE('-');\r
-}\r
-\r
-/**\r
- * \fn int BGA_int_UpdateMode(int id)\r
- * \brief Set current vide mode given a mode id\r
- */\r
-int BGA_int_UpdateMode(int id)\r
-{\r
- // Sanity Check\r
- if(id < 0 || id >= BGA_MODE_COUNT) return -1;\r
- \r
- // Check if it is a text mode\r
- if( gBGA_Modes[id].flags & MODEFLAG_TEXT )\r
- BGA_int_SetMode(\r
- gBGA_Modes[id].width*giVT_CharWidth,\r
- gBGA_Modes[id].height*giVT_CharHeight);\r
- else // Graphics?\r
- BGA_int_SetMode(\r
- gBGA_Modes[id].width,\r
- gBGA_Modes[id].height);\r
- \r
- giBGA_CurrentMode = id;\r
- return id;\r
-}\r
-\r
-/**\r
- * \fn int BGA_int_FindMode(tVideo_IOCtl_Mode *info)\r
- * \brief Find a mode matching the given options\r
- */\r
-int BGA_int_FindMode(tVideo_IOCtl_Mode *info)\r
-{\r
- int i;\r
- int best = 0, bestFactor = 1000;\r
- int factor, tmp;\r
- int rqdProduct = info->width * info->height * info->bpp;\r
- \r
- ENTER("pinfo", info);\r
- LOG("info = {width:%i,height:%i,bpp:%i})\n", info->width, info->height, info->bpp);\r
- \r
- for(i = 0; i < BGA_MODE_COUNT; i++)\r
- {\r
- #if DEBUG >= 2\r
- LogF("Mode %i (%ix%ix%i), ", i, gBGA_Modes[i].width, gBGA_Modes[i].height, gBGA_Modes[i].bpp);\r
- #endif\r
- \r
- // Check if this mode is the same type as what we want\r
- if( !(gBGA_Modes[i].flags & MODEFLAG_TEXT) != !(info->flags & VIDEO_FLAG_TEXT) )\r
- continue;\r
- \r
- // Ooh! A perfect match\r
- if(gBGA_Modes[i].width == info->width\r
- && gBGA_Modes[i].height == info->height\r
- && gBGA_Modes[i].bpp == info->bpp)\r
- {\r
- #if DEBUG >= 2\r
- LogF("Perfect!\n");\r
- #endif\r
- best = i;\r
- break;\r
- }\r
- \r
- // If not, how close are we?\r
- tmp = gBGA_Modes[i].width * gBGA_Modes[i].height * gBGA_Modes[i].bpp;\r
- tmp -= rqdProduct;\r
- tmp = tmp < 0 ? -tmp : tmp; // tmp = ABS(tmp)\r
- factor = tmp * 100 / rqdProduct;\r
- \r
- #if DEBUG >= 2\r
- LogF("factor = %i\n", factor);\r
- #endif\r
- \r
- if(factor < bestFactor)\r
- {\r
- bestFactor = factor;\r
- best = i;\r
- }\r
- }\r
- \r
- info->id = best;\r
- info->width = gBGA_Modes[best].width;\r
- info->height = gBGA_Modes[best].height;\r
- info->bpp = gBGA_Modes[best].bpp;\r
- \r
- info->flags = 0;\r
- if(gBGA_Modes[best].flags & MODEFLAG_TEXT)\r
- info->flags |= VIDEO_FLAG_TEXT;\r
- \r
- return best;\r
-}\r
-\r
-/**\r
- * \fn int BGA_int_ModeInfo(tVideo_IOCtl_Mode *info)\r
- * \brief Get mode information\r
- */\r
-int BGA_int_ModeInfo(tVideo_IOCtl_Mode *info)\r
-{\r
- // Sanity Check\r
- //if( !MM_IsUser( (Uint)info, sizeof(tVideo_IOCtl_Mode) ) ) {\r
- // return -EINVAL;\r
- //}\r
- \r
- if(info->id < 0 || info->id >= BGA_MODE_COUNT) return -1;\r
- \r
- info->width = gBGA_Modes[info->id].width;\r
- info->height = gBGA_Modes[info->id].height;\r
- info->bpp = gBGA_Modes[info->id].bpp;\r
- \r
- info->flags = 0;\r
- if(gBGA_Modes[info->id].flags & MODEFLAG_TEXT)\r
- info->flags |= VIDEO_FLAG_TEXT;\r
- \r
- return 1;\r
-}\r
-\r
-/**\r
- * \fn int BGA_int_MapFB(void *Dest)\r
- * \brief Map the framebuffer into a process's space\r
- * \param Dest User address to load to\r
- */\r
-int BGA_int_MapFB(void *Dest)\r
-{\r
- Uint i;\r
- Uint pages;\r
- \r
- // Sanity Check\r
- if((Uint)Dest > 0xC0000000) return 0;\r
- if(gBGA_Modes[giBGA_CurrentMode].bpp < 15) return 0; // Only non-pallete modes are supported\r
- \r
- // Count required pages\r
- pages = (gBGA_Modes[giBGA_CurrentMode].fbSize + 0xFFF) >> 12;\r
- \r
- // Check if there is space\r
- for( i = 0; i < pages; i++ )\r
- {\r
- if(MM_GetPhysAddr( (Uint)Dest + (i << 12) ))\r
- return 0;\r
- }\r
- \r
- // Map\r
- for( i = 0; i < pages; i++ )\r
- MM_Map( (Uint)Dest + (i<<12), VBE_DISPI_LFB_PHYSICAL_ADDRESS + (i<<12) );\r
- \r
- return 1;\r
-}\r
--- /dev/null
+#
+#
+
+OBJ = ext2.o read.o dir.o write.o
+NAME = FS_Ext2
+
+-include ../Makefile.tpl
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*\r
+ * Acess OS\r
+ * Ext2 Driver Version 1\r
+ */\r
+/**\r
+ * \file fs/ext2.c\r
+ * \brief Second Extended Filesystem Driver\r
+ * \todo Implement file full write support\r
+ */\r
+#define DEBUG 1\r
+#define VERBOSE 0\r
+#include "ext2_common.h"\r
+#include <modules.h>\r
+\r
+// === PROTOTYPES ===\r
+ int Ext2_Install(char **Arguments);\r
+// Interface Functions\r
+tVFS_Node *Ext2_InitDevice(char *Device, char **Options);\r
+void Ext2_Unmount(tVFS_Node *Node);\r
+void Ext2_CloseFile(tVFS_Node *Node);\r
+// Internal Helpers\r
+ int Ext2_int_GetInode(tVFS_Node *Node, tExt2_Inode *Inode);\r
+Uint64 Ext2_int_GetBlockAddr(tExt2_Disk *Disk, Uint32 *Blocks, int BlockNum);\r
+Uint32 Ext2_int_AllocateInode(tExt2_Disk *Disk, Uint32 Parent);\r
+void Ext2_int_UpdateSuperblock(tExt2_Disk *Disk);\r
+\r
+// === SEMI-GLOBALS ===\r
+MODULE_DEFINE(0, 0x5B /*v0.90*/, FS_Ext2, Ext2_Install, NULL);\r
+tExt2_Disk gExt2_disks[6];\r
+ int giExt2_count = 0;\r
+tVFS_Driver gExt2_FSInfo = {\r
+ "ext2", 0, Ext2_InitDevice, Ext2_Unmount, NULL\r
+ };\r
+\r
+// === CODE ===\r
+\r
+/**\r
+ * \fn int Ext2_Install(char **Arguments)\r
+ * \brief Install the Ext2 Filesystem Driver\r
+ */\r
+int Ext2_Install(char **Arguments)\r
+{\r
+ VFS_AddDriver( &gExt2_FSInfo );\r
+ return 1;\r
+}\r
+\r
+/**\r
+ \fn tVFS_Node *Ext2_InitDevice(char *Device, char **Options)\r
+ \brief Initializes a device to be read by by the driver\r
+ \param Device String - Device to read from\r
+ \param Options NULL Terminated array of option strings\r
+ \return Root Node\r
+*/\r
+tVFS_Node *Ext2_InitDevice(char *Device, char **Options)\r
+{\r
+ tExt2_Disk *disk;\r
+ int fd;\r
+ int groupCount;\r
+ tExt2_SuperBlock sb;\r
+ tExt2_Inode inode;\r
+ \r
+ ENTER("sDevice pOptions", Device, Options);\r
+ \r
+ // Open Disk\r
+ fd = VFS_Open(Device, VFS_OPENFLAG_READ|VFS_OPENFLAG_WRITE); //Open Device\r
+ if(fd == -1) {\r
+ Warning("[EXT2 ] Unable to open '%s'", Device);\r
+ LEAVE('n');\r
+ return NULL;\r
+ }\r
+ \r
+ // Read Superblock at offset 1024\r
+ VFS_ReadAt(fd, 1024, 1024, &sb); // Read Superblock\r
+ \r
+ // Sanity Check Magic value\r
+ if(sb.s_magic != 0xEF53) {\r
+ Warning("[EXT2 ] Volume '%s' is not an EXT2 volume", Device);\r
+ VFS_Close(fd);\r
+ LEAVE('n');\r
+ return NULL;\r
+ }\r
+ \r
+ // Get Group count\r
+ groupCount = DivUp(sb.s_blocks_count, sb.s_blocks_per_group);\r
+ LOG("groupCount = %i", groupCount);\r
+ \r
+ // Allocate Disk Information\r
+ disk = malloc(sizeof(tExt2_Disk) + sizeof(tExt2_Group)*groupCount);\r
+ if(!disk) {\r
+ Warning("[EXT2 ] Unable to allocate disk structure");\r
+ VFS_Close(fd);\r
+ LEAVE('n');\r
+ return NULL;\r
+ }\r
+ disk->FD = fd;\r
+ memcpy(&disk->SuperBlock, &sb, 1024);\r
+ disk->GroupCount = groupCount;\r
+ \r
+ // Get an inode cache handle\r
+ disk->CacheID = Inode_GetHandle();\r
+ \r
+ // Get Block Size\r
+ LOG("s_log_block_size = 0x%x", sb.s_log_block_size);\r
+ disk->BlockSize = 1024 << sb.s_log_block_size;\r
+ \r
+ // Read Group Information\r
+ VFS_ReadAt(\r
+ disk->FD,\r
+ sb.s_first_data_block * disk->BlockSize + 1024,\r
+ sizeof(tExt2_Group)*groupCount,\r
+ disk->Groups\r
+ );\r
+ \r
+ #if VERBOSE\r
+ LOG("Block Group 0");\r
+ LOG(".bg_block_bitmap = 0x%x", disk->Groups[0].bg_block_bitmap);\r
+ LOG(".bg_inode_bitmap = 0x%x", disk->Groups[0].bg_inode_bitmap);\r
+ LOG(".bg_inode_table = 0x%x", disk->Groups[0].bg_inode_table);\r
+ LOG("Block Group 1");\r
+ LOG(".bg_block_bitmap = 0x%x", disk->Groups[1].bg_block_bitmap);\r
+ LOG(".bg_inode_bitmap = 0x%x", disk->Groups[1].bg_inode_bitmap);\r
+ LOG(".bg_inode_table = 0x%x", disk->Groups[1].bg_inode_table);\r
+ #endif\r
+ \r
+ // Get root Inode\r
+ Ext2_int_ReadInode(disk, 2, &inode);\r
+ \r
+ // Create Root Node\r
+ memset(&disk->RootNode, 0, sizeof(tVFS_Node));\r
+ disk->RootNode.Inode = 2; // Root inode ID\r
+ disk->RootNode.ImplPtr = disk; // Save disk pointer\r
+ disk->RootNode.Size = -1; // Fill in later (on readdir)\r
+ disk->RootNode.Flags = VFS_FFLAG_DIRECTORY;\r
+ \r
+ disk->RootNode.ReadDir = Ext2_ReadDir;\r
+ disk->RootNode.FindDir = Ext2_FindDir;\r
+ //disk->RootNode.Relink = Ext2_Relink;\r
+ \r
+ // Complete root node\r
+ disk->RootNode.UID = inode.i_uid;\r
+ disk->RootNode.GID = inode.i_gid;\r
+ disk->RootNode.NumACLs = 1;\r
+ disk->RootNode.ACLs = &gVFS_ACL_EveryoneRW;\r
+ \r
+ #if DEBUG\r
+ LOG("inode.i_size = 0x%x", inode.i_size);\r
+ LOG("inode.i_block[0] = 0x%x", inode.i_block[0]);\r
+ #endif\r
+ \r
+ LEAVE('p', &disk->RootNode);\r
+ return &disk->RootNode;\r
+}\r
+\r
+/**\r
+ * \fn void Ext2_Unmount(tVFS_Node *Node)\r
+ * \brief Close a mounted device\r
+ */\r
+void Ext2_Unmount(tVFS_Node *Node)\r
+{\r
+ tExt2_Disk *disk = Node->ImplPtr;\r
+ \r
+ VFS_Close( disk->FD );\r
+ Inode_ClearCache( disk->CacheID );\r
+ memset(disk, 0, sizeof(tExt2_Disk)+disk->GroupCount*sizeof(tExt2_Group));\r
+ free(disk);\r
+}\r
+\r
+/**\r
+ * \fn void Ext2_CloseFile(tVFS_Node *Node)\r
+ * \brief Close a file (Remove it from the cache)\r
+ */\r
+void Ext2_CloseFile(tVFS_Node *Node)\r
+{\r
+ tExt2_Disk *disk = Node->ImplPtr;\r
+ Inode_UncacheNode(disk->CacheID, Node->Inode);\r
+ return ;\r
+}\r
+\r
+//==================================\r
+//= INTERNAL FUNCTIONS =\r
+//==================================\r
+\r
+\r
+/**\r
+ * \fn int Ext2_int_GetInode(tVFS_Node *Node, tExt2_Inode *Inode)\r
+ * \brief Gets the inode descriptor for a node\r
+ * \param Node node to get the Inode of\r
+ * \param Inode Destination\r
+ */\r
+int Ext2_int_GetInode(tVFS_Node *Node, tExt2_Inode *Inode)\r
+{\r
+ return Ext2_int_ReadInode(Node->ImplPtr, Node->Inode, Inode);\r
+}\r
+\r
+/**\r
+ * \fn int Ext2_int_ReadInode(tExt2_Disk *Disk, Uint InodeId, tExt2_Inode *Inode)\r
+ * \brief Read an inode into memory\r
+ */\r
+int Ext2_int_ReadInode(tExt2_Disk *Disk, Uint InodeId, tExt2_Inode *Inode)\r
+{\r
+ int group, subId;\r
+ \r
+ //LogF("Ext2_int_ReadInode: (Disk=%p, InodeId=%i, Inode=%p)", Disk, InodeId, Inode);\r
+ //ENTER("pDisk iInodeId pInode", Disk, InodeId, Inode);\r
+ \r
+ if(InodeId == 0) return 0;\r
+ \r
+ InodeId --; // Inodes are numbered starting at 1\r
+ \r
+ group = InodeId / Disk->SuperBlock.s_inodes_per_group;\r
+ subId = InodeId % Disk->SuperBlock.s_inodes_per_group;\r
+ \r
+ //LOG("group=%i, subId = %i", group, subId);\r
+ \r
+ // Read Inode\r
+ VFS_ReadAt(Disk->FD,\r
+ Disk->Groups[group].bg_inode_table * Disk->BlockSize + sizeof(tExt2_Inode)*subId,\r
+ sizeof(tExt2_Inode),\r
+ Inode);\r
+ return 1;\r
+}\r
+\r
+/**\r
+ * \fn Uint64 Ext2_int_GetBlockAddr(tExt2_Disk *Disk, Uint32 *Blocks, int BlockNum)\r
+ * \brief Get the address of a block from an inode's list\r
+ * \param Disk Disk information structure\r
+ * \param Blocks Pointer to an inode's block list\r
+ * \param BlockNum Block index in list\r
+ */\r
+Uint64 Ext2_int_GetBlockAddr(tExt2_Disk *Disk, Uint32 *Blocks, int BlockNum)\r
+{\r
+ Uint32 *iBlocks;\r
+ // Direct Blocks\r
+ if(BlockNum < 12)\r
+ return (Uint64)Blocks[BlockNum] * Disk->BlockSize;\r
+ \r
+ // Single Indirect Blocks\r
+ iBlocks = malloc( Disk->BlockSize );\r
+ VFS_ReadAt(Disk->FD, (Uint64)Blocks[12]*Disk->BlockSize, Disk->BlockSize, iBlocks);\r
+ \r
+ BlockNum -= 12;\r
+ if(BlockNum < 256) {\r
+ BlockNum = iBlocks[BlockNum];\r
+ free(iBlocks);\r
+ return (Uint64)BlockNum * Disk->BlockSize;\r
+ }\r
+ \r
+ // Double Indirect Blocks\r
+ if(BlockNum < 256*256)\r
+ {\r
+ VFS_ReadAt(Disk->FD, (Uint64)Blocks[13]*Disk->BlockSize, Disk->BlockSize, iBlocks);\r
+ VFS_ReadAt(Disk->FD, (Uint64)iBlocks[BlockNum/256]*Disk->BlockSize, Disk->BlockSize, iBlocks);\r
+ BlockNum = iBlocks[BlockNum%256];\r
+ free(iBlocks);\r
+ return (Uint64)BlockNum * Disk->BlockSize;\r
+ }\r
+ // Triple Indirect Blocks\r
+ VFS_ReadAt(Disk->FD, (Uint64)Blocks[14]*Disk->BlockSize, Disk->BlockSize, iBlocks);\r
+ VFS_ReadAt(Disk->FD, (Uint64)iBlocks[BlockNum/(256*256)]*Disk->BlockSize, Disk->BlockSize, iBlocks);\r
+ VFS_ReadAt(Disk->FD, (Uint64)iBlocks[(BlockNum/256)%256]*Disk->BlockSize, Disk->BlockSize, iBlocks);\r
+ BlockNum = iBlocks[BlockNum%256];\r
+ free(iBlocks);\r
+ return (Uint64)BlockNum * Disk->BlockSize;\r
+}\r
+\r
+/**\r
+ * \fn Uint32 Ext2_int_AllocateInode(tExt2_Disk *Disk, Uint32 Parent)\r
+ * \brief Allocate an inode (from the current group preferably)\r
+ * \param Disk EXT2 Disk Information Structure\r
+ * \param Parent Inode ID of the parent (used to locate the child nearby)\r
+ */\r
+Uint32 Ext2_int_AllocateInode(tExt2_Disk *Disk, Uint32 Parent)\r
+{\r
+// Uint block = (Parent - 1) / Disk->SuperBlock.s_inodes_per_group;\r
+ return 0;\r
+}\r
+\r
+/**\r
+ * \fn void Ext2_int_UpdateSuperblock(tExt2_Disk *Disk)\r
+ * \brief Updates the superblock\r
+ */\r
+void Ext2_int_UpdateSuperblock(tExt2_Disk *Disk)\r
+{\r
+ int bpg = Disk->SuperBlock.s_blocks_per_group;\r
+ int ngrp = Disk->SuperBlock.s_blocks_count / bpg;\r
+ int i;\r
+ \r
+ // Update Primary\r
+ VFS_WriteAt(Disk->FD, 1024, 1024, &Disk->SuperBlock);\r
+ \r
+ // Secondaries\r
+ // at Block Group 1, 3^n, 5^n, 7^n\r
+ \r
+ // 1\r
+ if(ngrp <= 1) return;\r
+ VFS_WriteAt(Disk->FD, 1*bpg*Disk->BlockSize, 1024, &Disk->SuperBlock);\r
+ \r
+ // Powers of 3\r
+ for( i = 3; i < ngrp; i *= 3 )\r
+ VFS_WriteAt(Disk->FD, i*bpg*Disk->BlockSize, 1024, &Disk->SuperBlock);\r
+ \r
+ // Powers of 5\r
+ for( i = 5; i < ngrp; i *= 5 )\r
+ VFS_WriteAt(Disk->FD, i*bpg*Disk->BlockSize, 1024, &Disk->SuperBlock);\r
+ \r
+ // Powers of 7\r
+ for( i = 7; i < ngrp; i *= 7 )\r
+ VFS_WriteAt(Disk->FD, i*bpg*Disk->BlockSize, 1024, &Disk->SuperBlock);\r
+}\r
--- /dev/null
+/*
+ * Acess OS
+ * Ext2 Driver Version 1
+ */
+/**
+ * \file ext2_common.h
+ * \brief Second Extended Filesystem Driver
+ */
+#ifndef _EXT2_COMMON_H
+#define _EXT2_COMMON_H
+#include <common.h>
+#include <vfs.h>
+#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
--- /dev/null
+/**\r
+ * Acess2\r
+ * \file ext2fs.h\r
+ * \brief EXT2 Filesystem Driver\r
+ */\r
+#ifndef _EXT2FS_H_\r
+#define _EXT2FS_H_\r
+\r
+/**\r
+ \name Inode Flag Values\r
+ \{\r
+*/\r
+#define EXT2_S_IFMT 0xF000 //!< Format Mask\r
+#define EXT2_S_IFSOCK 0xC000 //!< Socket\r
+#define EXT2_S_IFLNK 0xA000 //!< Symbolic Link\r
+#define EXT2_S_IFREG 0x8000 //!< Regular File\r
+#define EXT2_S_IFBLK 0x6000 //!< Block Device\r
+#define EXT2_S_IFDIR 0x4000 //!< Directory\r
+#define EXT2_S_IFCHR 0x2000 //!< Character Device\r
+#define EXT2_S_IFIFO 0x1000 //!< FIFO\r
+#define EXT2_S_ISUID 0x0800 //!< SUID\r
+#define EXT2_S_ISGID 0x0400 //!< SGID\r
+#define EXT2_S_ISVTX 0x0200 //!< sticky bit\r
+#define EXT2_S_IRWXU 0700 //!< user access rights mask\r
+#define EXT2_S_IRUSR 0400 //!< Owner Read\r
+#define EXT2_S_IWUSR 0200 //!< Owner Write\r
+#define EXT2_S_IXUSR 0100 //!< Owner Execute\r
+#define EXT2_S_IRWXG 0070 //!< Group Access rights mask\r
+#define EXT2_S_IRGRP 0040 //!< Group Read\r
+#define EXT2_S_IWGRP 0020 //!< Group Write\r
+#define EXT2_S_IXGRP 0010 //!< Group Execute\r
+#define EXT2_S_IRWXO 0007 //!< Global Access rights mask\r
+#define EXT2_S_IROTH 0004 //!< Global Read\r
+#define EXT2_S_IWOTH 0002 //!< Global Write\r
+#define EXT2_S_IXOTH 0001 //!< Global Execute\r
+//! \}\r
+\r
+#define EXT2_NAME_LEN 255 //!< Maximum Name Length\r
+\r
+// === TYPEDEFS ===\r
+typedef struct ext2_inode_s tExt2_Inode; //!< Inode Type\r
+typedef struct ext2_super_block_s tExt2_SuperBlock; //!< Superblock Type\r
+typedef struct ext2_group_desc_s tExt2_Group; //!< Group Descriptor Type\r
+typedef struct ext2_dir_entry_s tExt2_DirEnt; //!< Directory Entry Type\r
+\r
+// === STRUCTURES ===\r
+/**\r
+ * \brief EXT2 Superblock Structure\r
+ */\r
+struct ext2_super_block_s {\r
+ Uint32 s_inodes_count; //!< Inodes count\r
+ Uint32 s_blocks_count; //!< Blocks count\r
+ Uint32 s_r_blocks_count; //!< Reserved blocks count\r
+ Uint32 s_free_blocks_count; //!< Free blocks count\r
+ Uint32 s_free_inodes_count; //!< Free inodes count\r
+ Uint32 s_first_data_block; //!< First Data Block\r
+ Uint32 s_log_block_size; //!< Block size\r
+ Sint32 s_log_frag_size; //!< Fragment size\r
+ Uint32 s_blocks_per_group; //!< Number Blocks per group\r
+ Uint32 s_frags_per_group; //!< Number Fragments per group\r
+ Uint32 s_inodes_per_group; //!< Number Inodes per group\r
+ Uint32 s_mtime; //!< Mount time\r
+ Uint32 s_wtime; //!< Write time\r
+ Uint16 s_mnt_count; //!< Mount count\r
+ Sint16 s_max_mnt_count; //!< Maximal mount count\r
+ Uint16 s_magic; //!< Magic signature\r
+ Uint16 s_state; //!< File system state\r
+ Uint16 s_errors; //!< Behaviour when detecting errors\r
+ Uint16 s_pad; //!< Padding\r
+ Uint32 s_lastcheck; //!< time of last check\r
+ Uint32 s_checkinterval; //!< max. time between checks\r
+ Uint32 s_creator_os; //!< Formatting OS\r
+ Uint32 s_rev_level; //!< Revision level\r
+ Uint16 s_def_resuid; //!< Default uid for reserved blocks\r
+ Uint16 s_def_resgid; //!< Default gid for reserved blocks\r
+ Uint32 s_reserved[235]; //!< Padding to the end of the block\r
+};\r
+\r
+/**\r
+ * \struct ext2_inode_s\r
+ * \brief EXT2 Inode Definition\r
+ */\r
+struct ext2_inode_s {\r
+ Uint16 i_mode; //!< File mode\r
+ Uint16 i_uid; //!< Owner Uid\r
+ Uint32 i_size; //!< Size in bytes\r
+ Uint32 i_atime; //!< Access time\r
+ Uint32 i_ctime; //!< Creation time\r
+ Uint32 i_mtime; //!< Modification time\r
+ Uint32 i_dtime; //!< Deletion Time\r
+ Uint16 i_gid; //!< Group Id\r
+ Uint16 i_links_count; //!< Links count\r
+ Uint32 i_blocks; //!< Number of blocks allocated for the file\r
+ Uint32 i_flags; //!< File flags\r
+ union {\r
+ Uint32 linux_reserved1; //!< Linux: Reserved\r
+ Uint32 hurd_translator; //!< HURD: Translator\r
+ Uint32 masix_reserved1; //!< Masix: Reserved\r
+ } osd1; //!< OS dependent 1\r
+ Uint32 i_block[15]; //!< Pointers to blocks\r
+ Uint32 i_version; //!< File version (for NFS)\r
+ Uint32 i_file_acl; //!< File ACL\r
+ Uint32 i_dir_acl; //!< Directory ACL / Extended File Size\r
+ Uint32 i_faddr; //!< Fragment address\r
+ union {\r
+ struct {\r
+ Uint8 l_i_frag; //!< Fragment number\r
+ Uint8 l_i_fsize; //!< Fragment size\r
+ Uint16 i_pad1; //!< Padding\r
+ Uint32 l_i_reserved2[2]; //!< Reserved\r
+ } linux2;\r
+ struct {\r
+ Uint8 h_i_frag; //!< Fragment number\r
+ Uint8 h_i_fsize; //!< Fragment size\r
+ Uint16 h_i_mode_high; //!< Mode High Bits\r
+ Uint16 h_i_uid_high; //!< UID High Bits\r
+ Uint16 h_i_gid_high; //!< GID High Bits\r
+ Uint32 h_i_author; //!< Creator ID\r
+ } hurd2;\r
+ struct {\r
+ Uint8 m_i_frag; //!< Fragment number\r
+ Uint8 m_i_fsize; //!< Fragment size\r
+ Uint16 m_pad1; //!< Padding\r
+ Uint32 m_i_reserved2[2]; //!< reserved\r
+ } masix2;\r
+ } osd2; //!< OS dependent 2\r
+};\r
+\r
+/**\r
+ * \struct ext2_group_desc_s\r
+ * \brief EXT2 Group Descriptor\r
+ */\r
+struct ext2_group_desc_s {\r
+ Uint32 bg_block_bitmap; //!< Blocks bitmap block\r
+ Uint32 bg_inode_bitmap; //!< Inodes bitmap block\r
+ Uint32 bg_inode_table; //!< Inodes table block\r
+ Uint16 bg_free_blocks_count; //!< Free blocks count\r
+ Uint16 bg_free_inodes_count; //!< Free inodes count\r
+ Uint16 bg_used_dirs_count; //!< Directories count\r
+ Uint16 bg_pad; //!< Padding\r
+ Uint32 bg_reserved[3]; //!< Reserved\r
+};\r
+\r
+/**\r
+ * \brief EXT2 Directory Entry\r
+ * \note The name may take up less than 255 characters\r
+ */\r
+struct ext2_dir_entry_s {\r
+ Uint32 inode; //!< Inode number\r
+ Uint16 rec_len; //!< Directory entry length\r
+ Uint8 name_len; //!< Short Name Length\r
+ Uint8 type; //!< File Type\r
+ char name[]; //!< File name\r
+};\r
+\r
+#endif\r
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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;
+}
if(i == MAX_CONTROLLERS) {\r
Warning("[UHCI ] Over "EXPAND_STR(MAX_CONTROLLERS)" UHCI controllers detected, ignoring rest");\r
}\r
- LEAVE('i', 0);\r
- return 0;\r
+ LEAVE('i', i);\r
+ return i;\r
}\r
\r
/**\r
void UHCI_Cleanup()\r
{\r
}
-
-/**
- * \fn int UHCI_IOCtl(tVFS_Node *Node, int ID, void *Data)
- */
-int UHCI_IOCtl(tVFS_Node *Node, int ID, void *Data)
-{
- return 0;
+\r
+/**\r
+ * \brief Sends a packet to a device endpoint\r
+ */\r
+int UHCI_SendPacket(int ControllerId, int Device, int Endpoint, void *Data, int Length)\r
+{\r
+ return 0;\r
}\r
\r
// === INTERNAL FUNCTIONS ===\r
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
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.
+
+
/*\r
-AcessOS Basic Lib C\r
-\r
-lib.h\r
+ * Acess2 Basic Lib C\r
+ * lib.h\r
*/\r
#ifndef _LIB_H\r
#define _LIB_H\r
\r
+#include <stddef.h>\r
+#include <stdint.h>\r
+\r
#define BUILD_SO 1\r
\r
#if defined(BUILD_DLL)\r
\r
extern void *memcpy(void *dest, const void *src, size_t n);\r
\r
+typedef struct sCPUID tCPUID;\r
+\r
+struct sCPUID\r
+{\r
+ uint8_t SSE;\r
+ uint8_t SSE2;\r
+};\r
+\r
#endif\r
* AcessOS Basic C Library\r
*/\r
#include "stdio_int.h"\r
+#include "lib.h"\r
\r
+// === PROTOTYPES ===\r
+static void cpuid(uint32_t Num, uint32_t *EAX, uint32_t *EBX, uint32_t *EDX, uint32_t *ECX);\r
+\r
+// === GLOBALS ===\r
extern char **_envp;\r
extern struct sFILE _iob[];\r
extern struct sFILE *stdin;\r
extern struct sFILE *stdout;\r
extern struct sFILE *stderr;\r
+// --- CPU Features ---\r
+tCPUID gCPU_Features;\r
\r
+// === CODE ===\r
/**\r
* \fn int SoMain()\r
* \brief Stub Entrypoint\r
stderr = &_iob[2];\r
stderr->FD = 2; stderr->Flags = FILE_FLAG_MODE_WRITE;\r
\r
+ /*\r
+ {\r
+ uint32_t ecx, edx;\r
+ cpuid(1, NULL, NULL, &edx, &ecx);\r
+ gCPU_Features.SSE = edx & (1 << 25); // SSE\r
+ gCPU_Features.SSE2 = edx & (1 << 26); // SSE2\r
+ }\r
+ */\r
+ \r
return 1;\r
}\r
+\r
+\r
+/**\r
+ * \brief Call the CPUID opcode\r
+ */\r
+static void cpuid(uint32_t Num, uint32_t *EAX, uint32_t *EBX, uint32_t *EDX, uint32_t *ECX)\r
+{\r
+ uint32_t eax, ebx, edx, ecx;\r
+ \r
+ __asm__ __volatile__ (\r
+ "cpuid"\r
+ : "=a"(eax), "=c"(ecx), "=d"(edx)\r
+ : "a"(Num)\r
+ );\r
+ \r
+ if(EAX) *EAX = eax;\r
+ if(EBX) *EBX = ebx;\r
+ if(EDX) *EDX = edx;\r
+ if(ECX) *ECX = ecx;\r
+}\r
MSE_IOCTL_MAX_Y\r
};
+// === Terminal ===
+#include "devices/terminal.h"
+
#endif
--- /dev/null
+/**
+ * \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