# - The built objects and dependency files are suffixed with the arch name
# - The final binary is Acess2.<ARCH>.bin
--include Makefile.cfg
+-include ../Makefile.cfg
-include arch/$(ARCHDIR)/Makefile
-RM = rm -f
-
MAKEDEP = $(CC) -M
CPPFLAGS += -I./include -I./arch/$(ARCHDIR)/include -DARCH=$(ARCH)
@echo --- LD -o $(BIN)
@$(LD) $(LDFLAGS) -o $(BIN) $(OBJ) -Map ../Map.$(ARCH).txt
@objdump $(BIN) -D > $(BIN).dsm
- @cp $(BIN) /mnt/AcessFDD/
+ cp $(BIN) $(DISTROOT)
@wc -l $(SRCFILES) > LineCounts.$(ARCH).txt
- @git commit -a
+# @git commit -a
%.ao.$(ARCH): %.asm Makefile
@echo --- NASM -o $@
+++ /dev/null
-#
-# Acess2 Makefile Config
-# Makefile.cfg
-
-ARCH = i386
-ARCHDIR = x86
# arch/i386/Makefile
# Assuming build machine is 32-bit ELF
-CC = gcc
-AS = nasm
-LD = ld
-OBJDUMP = objdump
+#CC = gcc
+#AS = nasm
+#LD = ld
+#OBJDUMP = objdump
CPPFLAGS =
CFLAGS =
*/
#include <common.h>
+// === CONSTANTS ===
+#define MAX_BACKTRACE 8 //!< Maximum distance to trace the stack backwards
+
// === IMPORTS ===
extern void MM_PageFault(Uint Addr, Uint ErrorCode, tRegs *Regs);
extern void Threads_Dump();
+// === PROTOTYPES ===
+void Error_Backtrace(Uint eip, Uint ebp);
+
// === CODE ===
/**
* \fn void ErrorHandler(tRegs *Regs)
__asm__ __volatile__ ("mov %%cr3, %0":"=r"(cr));
Warning(" CR3: 0x%08x", cr);
+ // Print Stack Backtrace
+ Error_Backtrace(Regs->eip, Regs->ebp);
+
// Dump running threads
Threads_Dump();
for(;;) __asm__ __volatile__ ("hlt");
}
+/**
+ * \fn void Error_Backtrace(Uint eip, Uint ebp)
+ * \brief Unrolls the stack to trace execution
+ */
+void Error_Backtrace(Uint eip, Uint ebp)
+{
+ int i = 0;
+ Uint delta = 0;
+ char *str = NULL;
+
+ //if(eip < 0xC0000000 && eip > 0x1000)
+ //{
+ // LogF("Backtrace: User - 0x%x\n", eip);
+ // return;
+ //}
+
+ if(eip > 0xE0000000)
+ {
+ LogF("Backtrace: Data Area - 0x%x\n", eip);
+ return;
+ }
+
+ if(eip > 0xC8000000)
+ {
+ LogF("Backtrace: Kernel Module - 0x%x\n", eip);
+ return;
+ }
+
+ //str = Debug_GetSymbol(eip, &delta);
+ if(str == NULL)
+ LogF("Backtrace: 0x%x", eip);
+ else
+ LogF("Backtrace: %s+0x%x", str, delta);
+ if(!MM_GetPhysAddr(ebp))
+ {
+ LogF("\nBacktrace: Invalid EBP, stopping\n");
+ return;
+ }
+
+
+ while( MM_GetPhysAddr(ebp) && i < MAX_BACKTRACE )
+ {
+ //str = Debug_GetSymbol(*(Uint*)(ebp+4), &delta);
+ if(str == NULL)
+ LogF(" >> 0x%x", *(Uint*)(ebp+4));
+ else
+ LogF(" >> %s+0x%x", str, delta);
+ ebp = *(Uint*)ebp;
+ i++;
+ }
+ LogF("\n");
+}
extern Uint32 gaInitPageDir[1024];
extern Uint32 gaInitPageTable[1024];
extern void Threads_SegFault(Uint Addr);
+extern void Error_Backtrace(Uint eip, Uint ebp);
// === PROTOTYPES ===
void MM_PreinitVirtual();
);
}
+ Log("Code at %p accessed %p", Regs->eip, Addr);
+ // Print Stack Backtrace
+ Error_Backtrace(Regs->eip, Regs->ebp);
+
Log("gaPageDir[0x%x] = 0x%x", Addr>>22, gaPageDir[Addr>>22]);
if( gaPageDir[Addr>>22] & PF_PRESENT )
Log("gaPageTable[0x%x] = 0x%x", Addr>>12, gaPageTable[Addr>>12]);
- Log("Code at %p accessed %p\n", Regs->eip, Addr);
-
MM_DumpTables(0, -1);
Panic("Page Fault at 0x%x\n", Regs->eip);
extern tThread *gDeleteThreads;
extern tThread *Threads_GetNextToRun(int CPU);
extern void Threads_Dump();
+extern tThread *Threads_CloneTCB(Uint *Err, Uint Flags);
// === PROTOTYPES ===
void ArchThreads_Init();
__asm__ __volatile__ ("mov %%esp, %0": "=r"(esp));
__asm__ __volatile__ ("mov %%ebp, %0": "=r"(ebp));
- // Create new thread structure
- newThread = malloc( sizeof(tThread) );
- if(!newThread) {
- Warning("Proc_Clone - Out of memory when creating thread\n");
- *Err = -ENOMEM;
- return -1;
- }
-
- // Base new thread on current
- memcpy(newThread, cur, sizeof(tThread));
+ newThread = Threads_CloneTCB(Err, Flags);
+ if(!newThread) return -1;
// Initialise Memory Space (New Addr space or kernel stack)
if(Flags & CLONE_VM) {
- newThread->TGID = newThread->TID;
newThread->MemState.CR3 = MM_Clone();
+ newThread->KernelStack = cur->KernelStack;
} else {
Uint tmpEbp, oldEsp = esp;
+ // Set CR3
+ newThread->MemState.CR3 = cur->MemState.CR3;
+
// Create new KStack
newThread->KernelStack = MM_NewKStack();
// Check for errors
*(Uint*)tmpEbp += newThread->KernelStack - cur->KernelStack;
}
}
-
- // Set Pointer, Spinlock and TID
- newThread->Next = NULL;
- newThread->IsLocked = 0;
- newThread->TID = giNextTID++;
- newThread->PTID = cur->TID;
-
- // Create copy of name
- newThread->ThreadName = malloc(strlen(cur->ThreadName)+1);
- strcpy(newThread->ThreadName, cur->ThreadName);
-
- // Clear message list (messages are not inherited)
- newThread->Messages = NULL;
- newThread->LastMessage = NULL;
-
- // Set remaining (sheduler expects remaining to be correct)
- newThread->Remaining = newThread->Quantum;
// Save core machine state
newThread->SavedState.ESP = esp;
// Lock list and add to active
Threads_AddActive(newThread);
- //Threads_Dump();
-
return newThread->TID;
}
extern int Proc_Clone(Uint *Err, Uint Flags);\r
extern void Threads_SetName(char *Name);\r
extern char *Threads_GetName(int ID);\r
+extern void Threads_Exit(int, int);\r
extern Uint MM_ClearUser();\r
-extern void Threads_Exit();\r
extern void Proc_StartUser(Uint Entrypoint, Uint *Bases, int ArgC, char **ArgV, char **EnvP, int DataSize);\r
extern tKernelSymbol gKernelSymbols[];\r
extern void gKernelSymbolsEnd;\r
if(bases[0] == 0)\r
{\r
Warning("Proc_Execve - Unable to load '%s'", Threads_GetName(-1));\r
- Threads_Exit();\r
+ Threads_Exit(0, 0);\r
for(;;);\r
}\r
\r
cdat --;
}
E9('\n');
-
}
// --- EXPORTS ---
--- /dev/null
+/* Acess2
+ * NE2000 Driver
+ *
+ * See: ~/Sources/bochs/bochs.../iodev/ne2k.cc
+ */
+#include <common.h>
+#include <modules.h>
+#include <fs_devfs.h>
+
+// === CONSTANTS ===
+static const struct {
+ Uint16 Vendor;
+ Uint16 Device;
+} csaCOMPAT_DEVICES[] = {
+ {0x10EC, 0x8029}, // Realtek 8029
+ {0x10EC, 0x8129} // Realtek 8129
+};
+#define NUM_COMPAT_DEVICES (sizeof(csaCOMPAT_DEVICES)/sizeof(csaCOMPAT_DEVICES[0]))
+
+enum eNe2k_Page0Read {
+ COMMAND = 0, //!< the master command register
+ CLDA0, //!< Current Local DMA Address 0
+ CLDA1, //!< Current Local DMA Address 1
+ BNRY, //!< Boundary Pointer (for ringbuffer)
+ TSR, //!< Transmit Status Register
+ NCR, //!< collisions counter
+ FIFO, //!< (for what purpose ??)
+ ISR, //!< Interrupt Status Register
+ CRDA0, //!< Current Remote DMA Address 0
+ CRDA1, //!< Current Remote DMA Address 1
+ RSR = 0xC //!< Receive Status Register
+};
+
+enum eNe2k_Page0Write {
+ PTART = 1, //!< page start (init only)
+ PSTOP, //!< page stop (init only)
+ TPSR = 4, //!< transmit page start address
+ TBCR0, //!< transmit byte count (low)
+ TBCR1, //!< transmit byte count (high)
+ RSAR0 = 8, //!< remote start address (lo)
+ RSAR1, //!< remote start address (hi)
+ RBCR0, //!< remote byte count (lo)
+ RBCR1, //!< remote byte count (hi)
+ RCR, //!< receive config register
+ TCR, //!< transmit config register
+ DCR, //!< data config register (init)
+ IMR //!< interrupt mask register (init)
+};
+
+// === TYPES ===
+typedef struct sNe2k_Card {
+ Uint16 IOBase; //!< IO Port Address from PCI
+ Uint8 IRQ; //!< IRQ Assigned from PCI
+
+ int NextMemPage; //!< Next Card Memory page to use
+
+ char Name[2]; // "0"
+ tVFS_Node *Node;
+ char MacAddr[6];
+} tCard;
+
+// === PROTOTYPES ===
+ int Ne2k_Install(char **Arguments);
+Uint64 Ne2k_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
+
+// === GLOBALS ===
+MODULE_DEFINE(0, 0x0032, Ne2k, Ne2k_Install, NULL, NULL);
+tDevFS_Driver gNe2k_DriverInfo = {
+ NULL, "ne2k",
+ {
+ .NumACLs = 1,
+ .ACLs = &gVFS_ACL_EveryoneRW,
+ .Flags = VFS_FFLAG_DIRECTORY
+ }
+};
+Uint16 gNe2k_BaseAddress;
+ int giNe2k_CardCount = 0;
+
+// === CODE ===
+/**
+ * \fn int Ne2k_Install(char **Options)
+ * \brief Installs the NE2000 Driver
+ */
+int Ne2k_Install(char **Options)
+{
+ int i, j, k;
+
+ // --- Scan PCI Bus ---
+ // Count Cards
+ giNe2k_CardCount = 0;
+ for( i = 0; i < NUM_COMPAT_DEVICES; i ++ )
+ {
+ giNe2k_CardCount += PCI_CountDevices( csaCOMPAT_DEVICES[i].Vendor, csaCOMPAT_DEVICES[i].Device, 0 );
+ }
+
+ // Enumerate Cards
+ k = 0;
+ gpNe2k_Cards = malloc( giNe2k_CardCount * sizeof(tCard) );
+ memsetd(gpNe2k_Cards, 0, giNe2k_CardCount * sizeof(tCard) / 4);
+ for( i = 0; i < NUM_COMPAT_DEVICES; i ++ )
+ {
+ count = PCI_CountDevices( csaCOMPAT_DEVICES[i].Vendor, csaCOMPAT_DEVICES[i].Device, 0 );
+ for( j = 0; j < count; j ++,k ++ )
+ {
+ id = PCI_GetDevice( csaCOMPAT_DEVICES[i].Vendor, csaCOMPAT_DEVICES[i].Device, 0, j );
+ // Create Structure
+ base = PCI_AssignPort( id, 0, 0x20 );
+ gpNe2k_Cards[ k ].IOBase = base;
+ gpNe2k_Cards[ k ].IRQ = PCI_GetIRQ( id );
+ gpNe2k_Cards[ k ].NextMemPage = 1;
+
+ //Install IRQ6 Handler
+ IRQ_Set(gpNe2k_Cards[ k ].IRQ, Ne2k_IRQHandler);
+
+ // Reset Card
+ outb( base + 0x1F, inb(base + 0x1F) );
+ while( (inb( base+ISR ) & 0x80) == 0 );
+ outb( base + ISR, 0x80 );
+
+ // Initialise Card
+ outb( base + COMMAND, 0x21 ); // No DMA and Stop
+ outb( base + DCR, 0x49 ); // Set WORD mode
+ outb( base + IMR, 0x00 );
+ outb( base + ISR, 0xFF );
+ outb( base + RCR, 0x20 ); // Reciever to Monitor
+ outb( base + TCR, 0x02 ); // Transmitter OFF
+ outb( base + RBCR0, 6*4 ); // Remote Byte Count
+ outb( base + RBCR1, 0 );
+ outb( base + RSAR0, 0 ); // Clear Source Address
+ outb( base + RSAR1, 0 );
+ outb( base + COMMAND, 0x0A ); // Remote Read, Start
+
+ // Read MAC Address
+ gpNe2k_Cards[ k ].MacAddr[0] = inb(base+0x10); inb(base+0x10);
+ gpNe2k_Cards[ k ].MacAddr[1] = inb(base+0x10); inb(base+0x10);
+ gpNe2k_Cards[ k ].MacAddr[2] = inb(base+0x10); inb(base+0x10);
+ gpNe2k_Cards[ k ].MacAddr[3] = inb(base+0x10); inb(base+0x10);
+ gpNe2k_Cards[ k ].MacAddr[4] = inb(base+0x10); inb(base+0x10);
+ gpNe2k_Cards[ k ].MacAddr[5] = inb(base+0x10); inb(base+0x10);
+
+ outb( base+PSTART, 0x60); // Set Receive Start
+ outb( base+BNRY, 0x7F); // Set Boundary Page
+ outb( base+PSTOP, 0x80); // Set Stop Page
+ outb( base+ISR, 0xFF ); // Clear all ints
+ outb( base+CMD, 0x22 ); // No DMA, Start
+ outb( base+IMR, 0x3F ); // Set Interupt Mask
+ outb( base+RCR, 0x8F ); // Set WRAP and allow all packet matches
+ outb( base+TCR, 0x00 ); // Set Normal Transmitter mode
+ outb( base+TPSR, 0x40); // Set Transmit Start
+
+ // Set MAC Address
+ /*
+ Ne2k_WriteReg(base, MAC0, gpNe2k_Cards[ k ].MacAddr[0]);
+ Ne2k_WriteReg(base, MAC1, gpNe2k_Cards[ k ].MacAddr[1]);
+ Ne2k_WriteReg(base, MAC2, gpNe2k_Cards[ k ].MacAddr[2]);
+ Ne2k_WriteReg(base, MAC3, gpNe2k_Cards[ k ].MacAddr[3]);
+ Ne2k_WriteReg(base, MAC4, gpNe2k_Cards[ k ].MacAddr[4]);
+ Ne2k_WriteReg(base, MAC5, gpNe2k_Cards[ k ].MacAddr[5]);
+ */
+
+ Log("[NE2K]: Card #%i: IRQ=%i, Base=0x%x, ",
+ k, gpNe2k_Cards[ k ].IRQ, gpNe2k_Cards[ k ].PortBase,
+ gpNe2k_Cards[ k ].Buffer);
+ Log("MAC Address %x:%x:%x:%x:%x:%x\n",
+ gpNe2k_Cards[ k ].MacAddr[0], gpNe2k_Cards[ k ].MacAddr[1],
+ gpNe2k_Cards[ k ].MacAddr[2], gpNe2k_Cards[ k ].MacAddr[3],
+ gpNe2k_Cards[ k ].MacAddr[4], gpNe2k_Cards[ k ].MacAddr[5]
+ );
+
+ // Set VFS Node
+ gpNe2k_Cards[ k ].Name[0] = '0'+k;
+ gpNe2k_Cards[ k ].Name[1] = '\0';
+ gpNe2k_Cards[ k ].Node.NumACLs = 1;
+ gpNe2k_Cards[ k ].Node.ACLs = gVFS_ACL_EveryoneRW;
+ gpNe2k_Cards[ k ].Node.CTime = now();
+ gpNe2k_Cards[ k ].Node.Write = Ne2k_Write;
+ }
+ }
+
+ DevFS_AddDevice( &gNe2k_DriverInfo );
+ return 0;
+}
+
+
+/**
+ * \fn Uint64 Ne2k_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
+ */
+Uint64 Ne2k_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
+{
+ tCard *Card = (tCard*)Node->ImplPtr;
+
+ // Sanity Check Length
+ if(Length > 0xFFFF) return 0;
+
+ outb(Card->IOBase + COMMAND, 0|0x22); // Page 0, Start, NoDMA
+ // Send Size
+ outb(Card->IOBase + RBCR0, Count & 0xFF);
+ outb(Card->IOBase + RBCR1, Count >> 8);
+ // Clear Remote DMA Flag
+ outb(Card->IOBase + ISR, 0x40); // Bit 6
+ // Set up transfer
+ outb(Card->IOBase + RSAR0, 0x00); // Page Offset
+ outb(Card->IOBase + RSAR1, Ne2k_int_GetWritePage(Card, Length)); // Page Offset
+ return 0;
+}
+
+/**
+ * \fn Uint8 Ne2k_int_GetWritePage(tCard *Card, Uint16 Length)
+ */
+Uint8 Ne2k_int_GetWritePage(tCard *Card, Uint16 Length)
+{
+
+}
#include <arch.h>
#include <stdarg.h>
+enum eConfigTypes {
+ CFGT_NULL,
+ CFGT_INT,
+ CFGT_HEAPSTR,
+ CFGT_PTR
+};
enum eConfigs {
CFG_VFS_CWD,
CFG_VFS_MAXFILES,
NUM_CFG_ENTRIES
};
-#define CFGINT(_idx) (*(Uint*)(MM_PPD_CFG+(_idx)*sizeof(void*)))
-#define CFGPTR(_idx) (*(void**)(MM_PPD_CFG+(_idx)*sizeof(void*)))
+#define CFGINT(id) (*Threads_GetCfgPtr(id))
+#define CFGPTR(id) (*(void**)Threads_GetCfgPtr(id))
// === CONSTANTS ===
// --- Memory Flags --
extern void Warning(char *Msg, ...);
extern void Log(char *Fmt, ...);
extern void LogV(char *Fmt, va_list Args);
+extern void LogF(char *Fmt, ...);
extern void Debug_Enter(char *FuncName, char *ArgTypes, ...);
extern void Debug_Log(char *FuncName, char *Fmt, ...);
extern void Debug_Leave(char *FuncName, char RetType, ...);
extern void Threads_Exit();
extern void Threads_Yield();
extern void Threads_Sleep();
-extern int Threads_GetCfg(int Index);
extern int Threads_GetUID();
extern int Threads_GetGID();
extern int SpawnTask(tThreadFunction Function, void *Arg);
+extern Uint *Threads_GetCfgPtr(int Id);
#include <binary_ext.h>
#include <vfs_ext.h>
--- /dev/null
+/*
+ * Acess2 DMA Driver
+ */
+#ifndef _DMA_H_
+#define _DMA_H_
+
+extern void DMA_SetChannel(int channel, int length, int read);
+extern int DMA_ReadData(int channel, int count, void *buffer);
+
+#endif
--- /dev/null
+/*
+ * Acess2 Kernel
+ * Signal List
+ */
+#ifndef _SIGNAL_H_
+#define _SIGNAL_H_
+
+enum eSignals {
+ SIGKILL,
+ SIGSTOP,
+ SIGCONT,
+ SIGCHLD,
+ NSIG
+};
+
+#endif
typedef struct sThread
{
+ // --- threads.c's
struct sThread *Next; //!< Next thread in list
int IsLocked; //!< Thread's spinlock
int Status; //!< Thread Status
Uint UID, GID; //!< User and Group
char *ThreadName; //!< Name of thread
- tVAddr KernelStack; //!< Kernel Stack Base
+ // --- arch/proc.c's responsibility
+ //! Kernel Stack Base
+ tVAddr KernelStack;
//! Memory Manager State
tMemoryState MemState;
//! State on task switch
tTaskState SavedState;
+ // --- threads.c's
int CurSignal; //!< Signal currently being handled (0 for none)
tVAddr SignalHandlers[NSIG]; //!< Signal Handler List
tTaskState SignalState; //!< Saved state for signal handler
// Binary Control
// ---
case SYS_EXECVE:
+ if( !Syscall_ValidString(Regs->Arg1) ) {
+ err = -EINVAL;
+ ret = -1;
+ break;
+ }
ret = Proc_Execve((char*)Regs->Arg1, (char**)Regs->Arg2, (char**)Regs->Arg3);
break;
case SYS_LOADBIN:
int System_Int_GetString(char *Str, char **Dest);
// === GLOBALS ===
-char *gsInitPath = "/Acess/Bin/init";
char *gsConfigScript = "/Acess/Conf/BootConf.cfg";
// === CODE ===
*/
#include <common.h>
#include <threads.h>
+#include <errno.h>
// === CONSTANTS ===
#define DEFAULT_QUANTUM 10
#define DEFAULT_TICKETS 5
#define MAX_TICKETS 10
+const enum eConfigTypes cCONFIG_TYPES[] = {
+ CFGT_HEAPSTR, // CFG_VFS_CWD
+ CFGT_INT, // CFG_VFS_MAXFILES
+ CFGT_NULL
+};
// === IMPORTS ===
extern void ArchThreads_Init();
void Threads_SetName(char *NewName);
char *Threads_GetName(int ID);
void Threads_SetTickets(int Num);
+tThread *Threads_CloneTCB(Uint *Err, Uint Flags);
int Threads_WaitTID(int TID, int *status);
tThread *Threads_GetThread(Uint TID);
void Threads_AddToDelete(tThread *Thread);
RELEASE( &giThreadListLock );
}
+/**
+ * \fn tThread *Threads_CloneTCB(Uint *Err, Uint Flags)
+ */
+tThread *Threads_CloneTCB(Uint *Err, Uint Flags)
+{
+ tThread *cur, *new;
+ int i;
+ cur = Proc_GetCurThread();
+
+ new = malloc(sizeof(tThread));
+ if(new == NULL) {
+ *Err = -ENOMEM;
+ return NULL;
+ }
+
+ new->Next = NULL;
+ new->IsLocked = 0;
+ new->Status = THREAD_STAT_ACTIVE;
+ new->RetStatus = 0;
+
+ // Get Thread ID
+ new->TID = giNextTID++;
+ new->PTID = cur->TID;
+
+ // Clone Name
+ new->ThreadName = malloc(strlen(cur->ThreadName)+1);
+ strcpy(new->ThreadName, cur->ThreadName);
+
+ // Set Thread Group ID (PID)
+ if(Flags & CLONE_VM)
+ new->TGID = new->TID;
+ else
+ new->TGID = cur->TGID;
+
+ // Messages are not inherited
+ new->Messages = NULL;
+ new->LastMessage = NULL;
+
+ // Set State
+ new->Remaining = new->Quantum = cur->Quantum;
+ new->NumTickets = cur->NumTickets;
+
+ // Set Signal Handlers
+ new->CurSignal = 0;
+ if(Flags & CLONE_VM)
+ memset(new->SignalHandlers, 0, sizeof(new->SignalHandlers));
+ else
+ memcpy(new->SignalHandlers, cur->SignalHandlers, sizeof(new->SignalHandlers));
+ memset(&new->SignalState, 0, sizeof(tTaskState));
+
+ for( i = 0; i < NUM_CFG_ENTRIES; i ++ )
+ {
+ switch(cCONFIG_TYPES[i])
+ {
+ default:
+ new->Config[i] = cur->Config[i];
+ break;
+ case CFGT_HEAPSTR:
+ if(cur->Config[i])
+ new->Config[i] = (Uint) strdup( (void*)cur->Config[i] );
+ else
+ new->Config[i] = 0;
+ break;
+ }
+ }
+
+ return new;
+}
+
+/**
+ * \fn Uint *Threads_GetCfgPtr(int Id)
+ */
+Uint *Threads_GetCfgPtr(int Id)
+{
+ if(Id < 0 || Id >= NUM_CFG_ENTRIES) {
+ Warning("Threads_GetCfgPtr: Index %i is out of bounds", Id);
+ return NULL;
+ }
+
+ return &Proc_GetCurThread()->Config[Id];
+}
+
/**
* \fn void Threads_WaitTID(int TID, int *status)
* \brief Wait for a task to change state
}
-/**
+/**c0108919:
* \fn void Threads_Wake( tThread *Thread )
* \brief Wakes a sleeping/waiting thread up
*/
int ticket;
int number;
+ if(giNumActiveThreads == 0) return NULL;
+
// Special case: 1 thread
- if(giNumActiveThreads == 1)
- {
+ if(giNumActiveThreads == 1) {
return gActiveThreads;
}
--- /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 read support\r
+ */\r
+#include <common.h>\r
+#include <vfs.h>\r
+#include "fs_ext2.h"\r
+\r
+// === STRUCTURES ===\r
+typedef struct {\r
+ int FD;\r
+ int CacheID;\r
+ vfs_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
+//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
+char *Ext2_ReadDir(tVFS_Node *Node, int Pos);\r
+tVFS_Node *Ext2_FindDir(tVFS_Node *Node, char *FileName);\r
+tVFS_Node *Ext2_MkNod(tVFS_Node *Node, char *Name, Uint Flags);\r
+ int Ext2_int_GetInode(vfs_node *Node, tExt2_Inode *Inode);\r
+tVFS_Node *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeId, char *Name, Uint64 VfsInode);\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
+\r
+// === SEMI-GLOBALS ===\r
+tExt2_Disk gExt2_disks[6];\r
+ int giExt2_count = 0;\r
+tVFS_Driver gExt2_FSInfo = {NULL,\r
+ "ext2", 0, Ext2_InitDevice, Ext2_UnMount, NULL\r
+ };\r
+\r
+// === CODE ===\r
+\r
+/**\r
+ * \fn void Ext2_Install()\r
+ * \brief Install the Ext2 Filesystem Driver\r
+ */\r
+void Ext2_Install()\r
+{\r
+ VFS_AddDriver( &gExt2_FSInfo );\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
+ // 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'\n", Device);\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
+ WarningEx("EXT2", "Volume '%s' is not an EXT2 volume\n", Device);\r
+ VFS_Close(fd);\r
+ return NULL;\r
+ }\r
+ \r
+ // Get Group count\r
+ groupCount = DivUp(sb.s_blocks_count, sb.s_blocks_per_group);\r
+ //LogF(" Ext2_initDevice: groupCount = %i\n", groupCount);\r
+ \r
+ // Allocate Disk Information\r
+ disk = malloc(sizeof(tExt2_Disk) + sizeof(tExt2_Group)*groupCount);\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
+ //LogF(" Ext2_initDevice: s_log_block_size = 0x%x\n", sb.s_log_block_size);\r
+ disk->BlockSize = 1024 << sb.s_log_block_size;\r
+ \r
+ // Read Group Information\r
+ VFS_ReadAt(disk->fd,\r
+ sb.s_first_data_block * disk->BlockSize + 1024,\r
+ sizeof(tExt2_Group)*groupCount,\r
+ disk->Groups);\r
+ \r
+ #if 0\r
+ Log(" Ext2_initDevice: Block Group 0\n");\r
+ Log(" Ext2_initDevice: .bg_block_bitmap = 0x%x\n", disk->Groups[0].bg_block_bitmap);\r
+ Log(" Ext2_initDevice: .bg_inode_bitmap = 0x%x\n", disk->Groups[0].bg_inode_bitmap);\r
+ Log(" Ext2_initDevice: .bg_inode_table = 0x%x\n", disk->Groups[0].bg_inode_table);\r
+ Log(" Ext2_initDevice: Block Group 1\n");\r
+ Log(" Ext2_initDevice: .bg_block_bitmap = 0x%x\n", disk->Groups[1].bg_block_bitmap);\r
+ Log(" Ext2_initDevice: .bg_inode_bitmap = 0x%x\n", disk->Groups[1].bg_inode_bitmap);\r
+ Log(" Ext2_initDevice: .bg_inode_table = 0x%x\n", 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(vfs_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 0\r
+ Log(" Ext2_InitDevice: inode.i_size = 0x%x\n", inode.i_size);\r
+ Log(" Ext2_InitDevice: inode.i_block[0] = 0x%x\n", inode.i_block[0]);\r
+ #endif\r
+ \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
+ // Get Inode\r
+ Ext2_int_GetInode(Node, &inode);\r
+ \r
+ block = Offset / disk->BlockSize;\r
+ Offset = Offset / disk->BlockSize;\r
+ base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);\r
+ \r
+ // Read only block\r
+ if(Length <= disk->BlockSize - Offset)\r
+ {\r
+ VFS_ReadAt( disk->fd, base+Offset, Length, Buffer);\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
+ 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
+ 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
+ Ext2_int_GetInode(Node, &inode);\r
+ \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
+ if( Offset < allocSize )\r
+ {\r
+ if(Offset + Length > allocSize) {\r
+ bNewBlocks = 1;\r
+ retLen = allocSize - Offset;\r
+ } else\r
+ retLen = Length;\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
+ WarningEx("EXT2", "File extending is not yet supported");\r
+ \r
+ return 0;\r
+}\r
+\r
+/**\r
+ * \fn int Ext2_CloseFile(vfs_node *Node)\r
+ * \brief Close a file (Remove it from the cache)\r
+ */\r
+int Ext2_CloseFile(tVFS_Node *Node)\r
+{\r
+ tExt2_Disk *disk = Node->ImplPtr;\r
+ inode_uncacheNode(disk->CacheID, Node->impl);\r
+ return 1;\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
+ Uint64 vfsInode = 0;\r
+ tVFS_Node *retNode;\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\n", 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 ('%s') extends over a block boundary, ignoring\n",\r
+ entNum-1, Node->impl, Node->name);\r
+ }\r
+ ofs = 0;\r
+ Base = Ext2_int_GetBlockAddr( disk, inode.i_block, block );\r
+ }\r
+ }\r
+ \r
+ if(size <= 0) return NULL;\r
+ \r
+ // Read Entry\r
+ VFS_ReadAt( disk->fd, Base+ofs, sizeof(tExt2_DirEnt), &dirent );\r
+ //LOG(" Ext2_ReadDir: dirent.inode = %i\n", dirent.inode);\r
+ //LOG(" Ext2_ReadDir: dirent.rec_len = %i\n", dirent.rec_len);\r
+ //LOG(" Ext2_ReadDir: dirent.name_len = %i\n", 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
+ Warnin("[EXT2 ] Directory Entry %i of inode %i ('%s') extends over a block boundary, ignoring\n",\r
+ entNum-1, Node->impl, Node->name);\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 tVFS_Node *Ext2_MkNod(tVFS_Node *Parent, char *Name, int Flags)\r
+ * \brief Create a new node\r
+ */\r
+tVFS_Node *Ext2_MkNod(tVFS_Node *Parent, char *Name, int Flags)\r
+{\r
+ return 0;\r
+}\r
+\r
+//==================================\r
+//= INTERNAL FUNCTIONS =\r
+//==================================\r
+\r
+\r
+/**\r
+ \internal\r
+ \fn int Ext2_int_GetInode(vfs_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
+ break;\r
+ // Directory\r
+ case EXT2_S_IFDIR:\r
+ retNode.ReadRir = 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)\n", 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
+ //LogF(" Ext2_int_ReadInode: group=%i, subId = %i\n", group, subId);\r
+ \r
+ //Seek to Block - Absolute\r
+ vfs_seek(Disk->fd, Disk->Groups[group].bg_inode_table * Disk->BlockSize, SEEK_SET);\r
+ //Seeek to inode - Relative\r
+ vfs_seek(Disk->fd, sizeof(tExt2_Inode)*subId, SEEK_CUR);\r
+ vfs_read(Disk->fd, sizeof(tExt2_Inode), 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
--- /dev/null
+/**\r
+ Acess Version 1\r
+ \file fs_ext2_int.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
+//STRUCTURES\r
+/**\r
+ \struct ext2_super_block_s\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\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
+ \struct ext2_dir_entry\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
+//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
}
strcpy(ret, Path);
} else {
- cwdLen = strlen(cwd);
+ if(cwd == NULL) {
+ cwd = "/";
+ cwdLen = 1;
+ }
+ else {
+ cwdLen = strlen(cwd);
+ }
endLen = cwdLen + pathLen + 2;
// Prepend the current directory
ret = malloc(endLen);
write += (pos-read)+1;
}
+ ret[write] = '\0'; // Cap string (to deal with . or .. being the last terms)
// `ret` should now be the absolute path
LEAVE('s', ret);
//Log("VFS_GetAbsPath: RETURN '%s'", ret);
VFS_Close(fd);
// Free old working directory
- if( CFGPTR(CFG_VFS_CWD) ) free( CFGPTR(CFG_VFS_CWD) );
+ if( CFGPTR(CFG_VFS_CWD) )
+ free( CFGPTR(CFG_VFS_CWD) );
// Set new
CFGPTR(CFG_VFS_CWD) = buf;
--- /dev/null
+#
+# Acess2 Build Configuration
+#
+
+CC = gcc
+LD = ld
+AS = nasm
+OBJDUMP = objdump
+RM = @rm -f
+STRIP = strip
+
+ARCH = i386
+ARCHDIR = x86
+
+DISTROOT = /mnt/AcessHDD/Acess2
--- /dev/null
+========
+ Acess2
+========
+
+Acess2 is [TPG]'s hobby operating system.
+
+The Acess kernel is SEMI-posix compilant, but will be a comatability
+library that emulates the different functions.
+
+=== Source Tree ===
+--- /Kernel ---
+The /Kernel tree contains the kernel sources.
+ Within the root of the tree is the miscelanious architecture agnostic
+ code for managing threads, loading modules and other things.
+ /Kernel/arch/<archname> - Architecture dependent code
+ /Kernel/bin - Binary file format parsers. Takes a binary file and
+ convertes it into a binary object that the loader can then load into memory.
+ /Kernel/vfs - The Virtual Filesystem
+ /Kernel/vfs/fs - The various filesystem drivers for the VFS.
+ /Kernel/drv - Drivers
+
+--- Usermode ---
+/Usermode contains the base acess system
+ /Usermode/Applications - Usermode applications such as the default
+ command shell and the login shell.
+ /Usermode/Libraries - Usermode shared libraries and crt0.o, currently
+ implemented are libacess (kernel interface), a basic libc and ld-acess
+ (dynamic linker).
+ /Usermode/include - Required include files for the shared libraries.
+
+=== Building ===
# Project: Acess Shell\r
\r
-CC = gcc\r
-AS = nasm\r
-LD = ld\r
-RM = @rm -f\r
+-include ../Makefile.cfg\r
\r
-COBJ = main.o lib.o\r
-BIN = ../CLIShell\r
-ACESSDIR = /home/hodgeja/Projects/Acess2/Usermode\r
+CPPFLAGS += -I./include\r
+CFLAGS += -Wall -fno-builtin -fno-stack-protector\r
+LDFLAGS += \r
\r
-INCS = -I$(ACESSDIR)/include -I./include\r
-CFLAGS = -Wall -fno-builtin -fno-stack-protector $(INCS)\r
-ASFLAGS = -felf\r
-LDFLAGS = -T $(ACESSDIR)/Libraries/acess.ld -I /Acess/Libs/ld-acess.so -lc\r
+BIN = ../CLIShell\r
+COBJ = main.o lib.o\r
\r
.PHONY : all clean\r
\r
all: $(BIN)\r
\r
-$(BIN): $(AOBJ) $(COBJ)\r
+clean:\r
+ $(RM) $(COBJ) $(BIN)\r
+\r
+$(BIN): $(COBJ)\r
@echo --- $(LD) -o $@\r
- @$(LD) $(LDFLAGS) -o $@ $(AOBJ) $(COBJ) -Map Map.txt\r
+ @$(LD) $(LDFLAGS) -o $@ $(COBJ) -Map Map.txt\r
objdump -d $(BIN) > $(BIN).dsm\r
- cp $(BIN) /mnt/AcessHDD/Acess2/Bin/\r
-\r
-clean:\r
- $(RM) $(AOBJ) $(COBJ) $(BIN)\r
+ cp $(BIN) $(DISTROOT)/Bin/\r
\r
$(COBJ): %.o: %.c\r
@echo --- GCC -o $@\r
@$(CC) $(CFLAGS) -c $? -o $@\r
-\r
-$(AOBJ): %.ao: %.asm\r
- @echo --- $(AS) -o $@\r
- @$(AS) $(ASFLAGS) -o $@ $<\r
--- /dev/null
+# Acess 2 Applications
+# General Makefile
+
+-include ../../../Makefile.cfg
+
+ASFLAGS = -felf
+CPPFLAGS = -I../../include/
+CFLAGS = -fno-stack-protector $(CPPFLAGS)
+LDFLAGS = -T ../../Libraries/acess.ld -I /Acess/Libs/ld-acess.so -lc
# Project: cat\r
\r
-CC = gcc\r
-AS = nasm\r
-LD = ld\r
-RM = @rm -f\r
+-include ../Makefile.cfg\r
\r
COBJ = main.o
BIN = ../cat\r
-ACESSDIR = /home/hodgeja/Projects/Acess2/Usermode\r
\r
-INCS = -I$(ACESSDIR)/include -I./include\r
-CFLAGS = -Wall -fno-builtin -fno-stack-protector $(INCS)\r
-ASFLAGS = -felf\r
-LDFLAGS = -T $(ACESSDIR)/Libraries/acess.ld -I /Acess/Libs/ld-acess.so -lc\r
+CFLAGS += -Wall -fno-builtin -fno-stack-protector\r
+LDFLAGS += \r
\r
.PHONY : all clean\r
\r
@echo --- $(LD) -o $@\r
@$(LD) $(LDFLAGS) -o $@ $(COBJ) -Map Map.txt\r
objdump -d $(BIN) > $(BIN).dsm\r
- cp $(BIN) /mnt/AcessHDD/Acess2/Bin/\r
+ cp $(BIN) $(DISTROOT)/Bin/\r
\r
clean:\r
$(RM) $(COBJ) $(BIN)\r
#
-#
-#
-CC = gcc
-AS = nasm
-LD = ld
-RM = rm -f
+-include ../Makefile.cfg
-ASFLAGS = -felf
-CPPFLAGS = -nostdinc -I../../include
-CFLAGS = -Wall -Werror -O3 $(CPPFLAGS)
-LDFLAGS = -I/Acess/Libs/ld-acess.so -L../../Libraries ../../Libraries/crt0.o -lacess
+CPPFLAGS +=
+CFLAGS += -Wall -Werror -O3
+LDFLAGS +=
-OBJ = main.o
BIN = ../init
+OBJ = main.o
.PHONY: all clean
all: $(BIN)
+clean:
+ $(RM) $(BIN) $(OBJ)
+
$(BIN): $(OBJ) Makefile
$(LD) $(LDFLAGS) $(OBJ) -o $(BIN)
- cp $(BIN) /mnt/AcessHDD/Acess2/
+ cp $(BIN) $(DISTROOT)/SBin/
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
-#
-#
-#
+# Acess 2 Login Shell
-DBTYPE = tpl
+-include ../Makefile.cfg
-CC = gcc
-AS = nasm
-LD = ld
-RM = rm -f
+DBTYPE = tpl
-ASFLAGS = -felf
-CPPFLAGS = -I../../include
-CFLAGS = -fno-stack-protector -Wall -Werror -O3 $(CPPFLAGS)
-LDFLAGS = -I/Acess/Libs/ld-acess.so -L../../Libraries ../../Libraries/crt0.o -lacess -lgcc -lc
+CPPFLAGS +=
+CFLAGS += -fno-stack-protector -Wall -Werror -O3 $(CPPFLAGS)
+LDFLAGS += -lgcc -lc
OBJ = main.o database_$(DBTYPE).o
BIN = ../login
$(RM) $(BIN) $(OBJ)
$(BIN): $(OBJ)
- $(LD) $(LDFLAGS) $(OBJ) -o $(BIN)
- cp $(BIN) /mnt/AcessHDD/Acess2/SBin/
- objdump -d ../login > login.dsm
+ @echo --- $(LD) -o $@
+ @$(LD) $(LDFLAGS) $(OBJ) -o $@
+ cp $(BIN) $(DISTROOT)/SBin/
+ objdump -d $(BIN) > login.dsm
%.o: %.c Makefile
- $(CC) $(CFLAGS) -c $< -o $@
+ @echo --- $(CC) -o $@
+ @$(CC) $(CFLAGS) -c $< -o $@
--- /dev/null
+/*
+ * Acess2 Login Shell
+ */
+#ifndef _HEADER_H_
+#define _HEADER_H_
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <acess/sys.h>
+
+// === TYPES ===
+typedef struct {
+ int UID;
+ int GID;
+ char *Home;
+ char *Shell;
+} tUserInfo;
+
+// === PROTOTYPES ===
+// --- User Database ---
+extern int ValidateUser(char *Username, char *Password);
+extern tUserInfo *GetUserInfo(int UID);
+
+#endif
--- /dev/null
+# Project: cat\r
+\r
+-include ../Makefile.cfg\r
+\r
+COBJ = main.o
+BIN = ../ls\r
+\r
+CFLAGS += -Wall -fno-builtin\r
+LDFLAGS +=\r
+\r
+.PHONY : all clean\r
+\r
+all: $(BIN)\r
+\r
+$(BIN): $(COBJ)\r
+ @echo --- $(LD) -o $@\r
+ @$(LD) $(LDFLAGS) -o $@ $(COBJ) -Map Map.txt\r
+ objdump -d $(BIN) > $(BIN).dsm\r
+ cp $(BIN) $(DISTROOT)/Bin/\r
+\r
+clean:\r
+ $(RM) $(COBJ) $(BIN)\r
+\r
+$(COBJ): %.o: %.c\r
+ @echo --- GCC -o $@
+ @$(CC) $(CFLAGS) -c $? -o $@
+\r
--- /dev/null
+/*
+ * Acess2 LS command
+ */
+#include <acess/sys.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#define BUF_SIZE 1024
+
+// === PROTOTYPES ===
+ int main(int argc, char *argv[]);
+void ShowUsage(char *ProgName);
+void ParseArguments(int argc, char *argv[]);
+void SortFileList();
+
+// === GLOBALS ===
+// --- Flags ---
+ int gbShowAll = 0;
+ int gbShowImplicit = 0;
+ int gbViewExtended = 0;
+ int gbViewHumanReadable = 0;
+// --- Parameters ---
+char *gsDirectory = NULL;
+// --- Working Set ---
+char **gFileList;
+ int giNumFiles = 0;
+
+/**
+ * \fn int main(int argc, char *argv[])
+ * \brief Entrypoint
+ */
+int main(int argc, char *argv[])
+{
+ int fd, tmp;
+ char buf[BUF_SIZE+1];
+ t_sysFInfo info;
+ int space = 0;
+
+ // Arguments Check
+ ParseArguments(argc, argv);
+
+ // Open Directory
+ fd = open(gsDirectory, OPENFLAG_READ|OPENFLAG_EXEC);
+ if(fd == -1) {
+ printf("Unable to open '%s' for reading\n", gsDirectory);
+ return EXIT_FAILURE;
+ }
+
+ // Check that it is a directory
+ finfo(fd, &info, 0);
+ if( !(info.flags & FILEFLAG_DIRECTORY) ) {
+ fprintf(stderr, "'%s' is a directory\n", gsDirectory);
+ close(fd);
+ return EXIT_FAILURE;
+ }
+
+ // Traverse Directory
+ while( (tmp = readdir(fd, buf)) )
+ {
+ // Error check
+ if(tmp < 0) {
+ close(fd);
+ return EXIT_FAILURE;
+ }
+
+ // Allocate Space
+ if(space == giNumFiles)
+ {
+ space += 16;
+ gFileList = realloc(gFileList, space*sizeof(char*));
+ if(gFileList == NULL) {
+ close(fd);
+ return EXIT_FAILURE;
+ }
+ }
+ gFileList[giNumFiles++] = strdup(buf);
+ }
+
+ // Sort File List according to rules passed
+ SortFileList();
+
+ close(fd);
+ printf("\n");
+
+ return EXIT_SUCCESS;
+}
+
+/**
+ * \fn void ShowUsage(char *ProgName)
+ */
+void ShowUsage(char *ProgName)
+{
+ fprintf(stderr, "Usage: %s [options] [<directory>]\n", ProgName);
+ fprintf(stderr, "\n");
+}
+
+/**
+ * \fn void ParseArguments(int argc, char *argv[])
+ * \brief Parse the command line arguments
+ */
+void ParseArguments(int argc, char *argv[])
+{
+ int i;
+ char *str;
+ for( i = 1; i < argc; i ++ )
+ {
+ str = argv[i];
+ // Flags
+ if(str[0] == '-')
+ {
+ if(str[1] == '-')
+ {
+ continue;
+ }
+ str = &str[1];
+ for( ; *str; str++ )
+ {
+ switch(*str)
+ {
+ // Show All
+ case 'a': gbShowAll = 1; gbShowImplicit = 1; continue;
+ // Almost All
+ case 'A': gbShowAll = 1; gbShowImplicit = 0; continue;
+ // Extended List
+ case 'l': gbViewExtended = 1; continue;
+ // Human readable sizes
+ case 'h': gbViewHumanReadable = 1; continue;
+ default:
+ fprintf(stderr, "%s: Unknown option '%c'\n", *str);
+ ShowUsage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
+ }
+ continue;
+ }
+
+ if(gsDirectory == NULL) {
+ gsDirectory = argv[i];
+ }
+ }
+
+ // Apply Defaults
+ if(!gsDirectory) gsDirectory = ".";
+
+ printf("gsDirectory = '%s'\n", gsDirectory);
+}
+
+/**
+ * \fn int strcmpp(void *p1, void *p2)
+ * \brief Compares two strings given pointers to their pointers
+ */
+int strcmpp(const void *p1, const void *p2)
+{
+ return strcmp( *(char **)p1, *(char **)p2 );
+}
+
+/**
+ * \fn void SortFileList()
+ * \brief Sorts the filled file list
+ */
+void SortFileList()
+{
+ qsort(gFileList, giNumFiles, sizeof(char*), strcmpp);
+}
--- /dev/null
+# Acess 2 Libraries
+# General Makefile
+
+-include ../../../Makefile.cfg
+
+ASFLAGS = -felf
+CPPFLAGS = -I../../include/
+CFLAGS = -Wall -fPIC -fno-builtin -fno-stack-protector $(CPPFLAGS)
+LDFLAGS = -nostdlib -shared -I/Acess/Libs/ld-acess.so -e SoMain -x -L.. -lacess
# LD-ACESS.SO\r
# Makefile\r
\r
-CC = gcc\r
-AS = nasm\r
-RM = @rm -f\r
-LD = ld\r
-OBJDUMP = objdump\r
+-include ../Makefile.cfg\r
\r
COBJ = main.o lib.o loadlib.o elf.o pe.o\r
AOBJ = helpers.ao\r
BIN = ../ld-acess.so\r
\r
-CPPFLAGS = -I../../include\r
-CFLAGS = -Wall -fno-builtin -fleading-underscore -fno-stack-protector\r
-ASFLAGS = -felf\r
-#LDFLAGS = --oformat elf32-i386 -Map map.txt -Bstatic -e _SoMain -shared\r
-#LDFLAGS = --oformat elf32-i386 -Map map.txt -Bstatic -e _SoMain -Ttext 0xBFFFE000\r
-LDFLAGS = -T link.ld -Map map.txt -Bstatic\r
+CFLAGS = -Wall -fno-builtin -fleading-underscore -fno-stack-protector\r
+ASFLAGS = -felf\r
+LDFLAGS = -T link.ld -Map map.txt -Bstatic\r
\r
\r
.PHONY: all clean\r
$(RM) $(BIN) $(AOBJ) $(COBJ)\r
\r
$(BIN): $(AOBJ) $(COBJ)\r
- $(LD) $(LDFLAGS) -o $(BIN) $(AOBJ) $(COBJ) > link.txt\r
+ @echo --- $(LD) -shared -o $@\r
+ @$(LD) $(LDFLAGS) -o $(BIN) $(AOBJ) $(COBJ) > link.txt\r
$(OBJDUMP) -x $(BIN) > ld-acess.dmp\r
$(OBJDUMP) -d $(BIN) > ld-acess.dsm\r
- cp $(BIN) /mnt/AcessHDD/Acess2/Libs\r
+ cp $(BIN) $(DISTROOT)/Libs\r
\r
$(COBJ): %.o: %.c\r
- $(CC) $(CFLAGS) -o $@ -c $<\r
+ @echo $(CC) -o $@\r
+ @$(CC) $(CFLAGS) -o $@ -c $<\r
\r
$(AOBJ): %.ao: %.asm\r
- $(AS) $(ASFLAGS) -o $@ $<\r
+ @echo $(AS) -o $@\r
+ @$(AS) $(ASFLAGS) -o $@ $<\r
--- /dev/null
+; AcessOS 1\r
+; By thePowersGang\r
+; LD-ACESS.SO\r
+; - helpers.asm\r
+\r
+%include "../libacess.so_src/syscalls.inc.asm"\r
+\r
+[global _SysDebug]\r
+[global _SysExit]\r
+[global _SysLoadBin]\r
+[global _SysUnloadBin]\r
+\r
+; void SysDebugV(char *fmt, va_list Args)\r
+_SysDebug:\r
+ ;xchg bx, bx\r
+ push ebp\r
+ mov ebp, esp\r
+ pusha\r
+ \r
+ mov eax, 0x100 ; User Debug\r
+ mov ebx, [ebp+8] ; Format\r
+ mov ecx, [ebp+12] ; Arguments\r
+ mov edx, [ebp+16] ; Arguments\r
+ mov edi, [ebp+20] ; Arguments\r
+ mov esi, [ebp+24] ; Arguments\r
+ int 0xAC\r
+ \r
+ popa\r
+ pop ebp\r
+ ret\r
+\r
+; void SysExit()\r
+_SysExit:\r
+ push ebx\r
+ mov eax, SYS_EXIT ; Exit\r
+ mov ebx, [esp+0x8] ; Exit Code\r
+ int 0xAC\r
+ pop ebx\r
+ ret\r
+\r
+; Uint SysLoadBin(char *path, Uint *entry)\r
+_SysLoadBin:\r
+ push ebx\r
+ mov eax, SYS_LOADBIN ; SYS_LDBIN\r
+ mov ebx, [esp+0x8] ; Path\r
+ mov ecx, [esp+0xC] ; Entry\r
+ int 0xAC\r
+ pop ebx\r
+ ret\r
+\r
+; Uint SysUnloadBin(Uint Base)\r
+_SysUnloadBin:\r
+ push ebx\r
+ mov eax, SYS_UNLOADBIN ; SYS_ULDBIN\r
+ mov ebx, [esp+0x8] ; Base\r
+ int 0xAC\r
+ pop ebx\r
+ ret\r
--- /dev/null
+ENTRY(_SoMain)\r
+OUTPUT_FORMAT(elf32-i386)\r
+\r
+SECTIONS {\r
+ . = 0xBBFF0000;\r
+ _gLinkedBase = .;\r
+\r
+ .text : AT(ADDR(.text)) {\r
+ code = .;\r
+ *(.text)\r
+ *(.rodata*)\r
+ }\r
+\r
+ .data ALIGN (0x1000) : AT(ADDR(.data)) {\r
+ data = .;\r
+ *(.data)\r
+ }\r
+\r
+ .bss ALIGN (0x1000) : AT(ADDR(.bss)) {\r
+ _sbss = .;\r
+ *(COMMON)\r
+ *(.bss)\r
+ _ebss = .;\r
+ bss = .;\r
+ }\r
+ _end = .;\r
+}
#
#
-AS = nasm
-LD = ld
-STRIP = strip
-RM = rm -f
+-include ../../../Makefile.cfg
ASFLAGS = -felf
LDFLAGS = -nostdlib -shared -I/Acess/Libs/ld-acess.so -e SoMain
$(RM) $(BIN) $(OBJ)
$(BIN): $(OBJ)
- $(LD) $(LDFLAGS) -o $(BIN) $(OBJ)
+ @echo --- $(LD) -shared -o $@
+ @$(LD) $(LDFLAGS) -o $(BIN) $(OBJ)
$(STRIP) $(BIN)
- cp $(BIN) /mnt/AcessHDD/Acess2/Libs
+ cp $(BIN) $(DISTROOT)/Libs
%.ao: %.asm syscalls.inc.asm
- $(AS) $(ASFLAGS) -o $@ $<
+ @echo $(AS) -o $@
+ @$(AS) $(ASFLAGS) -o $@ $<
-# AcessOS Basic C Library\r
+# Acess2 Basic C Library\r
# Makefile\r
\r
-CC = gcc\r
-AS = nasm\r
-RM = @rm -f\r
-LD = ld\r
-OBJDUMP = objdump\r
-ACESSDIR = /home/hodgeja/Projects/Acess2\r
+-include ../Makefile.cfg\r
\r
-CPPFLAGS = -I$(ACESSDIR)/Usermode/include\r
-CFLAGS = -Wall -fPIC -fno-builtin -fno-stack-protector $(CPPFLAGS)\r
-ASFLAGS = -felf\r
-LDFLAGS = -x -shared -soname libc.so.1 -Map map.txt -e SoMain -L$(ACESSDIR)/Usermode/Libraries -lacess\r
+CPPFLAGS += \r
+CFLAGS += \r
+ASFLAGS +=\r
+LDFLAGS += -soname libc.so.1 -Map map.txt\r
\r
-OBJ_LIBC = heap.o stdlib.o stub.o env.o fileIO.o signals.o string.o\r
+OBJ_LIBC = heap.o stdlib.o stub.o env.o fileIO.o string.o\r
+# signals.o\r
BIN = ../libc.so.1\r
\r
.PHONY: all clean\r
$(OBJDUMP) -d $@ > libc.so.1.dsm\r
$(OBJDUMP) -x -r -R $@ > libc.so.1.dmp\r
cp ../libc.so.1 ../libc.so\r
- cp ../libc.so.1 /mnt/AcessHDD/Acess2/Libs/\r
+ cp ../libc.so.1 $(DISTROOT)/Libs/\r
\r
# C Runtime 0\r
../crt0.o: crt0.asm\r
--- /dev/null
+/*
+ * AcessOS Standard C Library
+ * CONFIG.H
+ * Configuration Options
+ */
+#ifndef _CONFIG_H
+# define _CONFIG_H
+
+// -- COMMON --
+#define _LIBC_BUILD 1
+#define DEBUG_BUILD 0
+
+// -- STDIO --
+#define STDIO_MAX_STREAMS 64
+#define STDIO_LOCAL_BUFFER 0
+
+#endif
--- /dev/null
+; AcessOS LibC\r
+; crt0.asm\r
+;\r
+\r
+[extern _heap_start]\r
+\r
+start:\r
+ \r
+ \r
--- /dev/null
+/*\r
+AcessOS Basic Lib C\r
+\r
+lib.h\r
+*/\r
+#ifndef _LIB_H\r
+#define _LIB_H\r
+\r
+#define BUILD_SO 1\r
+\r
+#if defined(BUILD_DLL)\r
+#define EXPORT __declspec(dllexport)\r
+#define LOCAL\r
+#elif defined(BUILD_SO)\r
+#define EXPORT\r
+#define LOCAL\r
+#endif\r
+\r
+#endif\r
--- /dev/null
+/*
+ * AcessOS Standard C Library
+ * SDTIO_INT.H
+ * Configuration Options
+ */
+#ifndef _STDIO_INT_H
+# define _STDIO_INT_H
+
+// === CONSTANTS ===
+#define FILE_FLAG_MODE_MASK 0x07
+#define FILE_FLAG_MODE_READ 0x01
+#define FILE_FLAG_MODE_WRITE 0x02
+#define FILE_FLAG_MODE_EXEC 0x03
+#define FILE_FLAG_MODE_APPEND 0x04
+#define FILE_FLAG_M_EXT 0x10
+
+// === TYPES ===
+struct sFILE {
+ int FD;
+ int Flags;
+ #if DEBUG_BUILD
+ char *FileName;
+ #endif
+ #if STDIO_LOCAL_BUFFER
+ char *Buffer;
+ Uint64 BufferStart;
+ int BufferSize;
+ #endif
+};
+
+#endif
--- /dev/null
+/*
+ * AcessOS Basic C Library
+ * string.c
+ */
+#include <acess/sys.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "lib.h"
+
+/**
+ * \fn EXPORT int strcmp(const char *s1, const char *s2)
+ * \brief Compare two strings
+ */
+EXPORT int strcmp(const char *s1, const char *s2)
+{
+ while(*s1 == *s2 && *s1 != '\0' && *s2 != '\0') {
+ s1++; s2++;
+ }
+ return (int)*s1 - (int)*s2;
+}
+
+/**
+ * \fn EXPORT char *strcpy(char *dst, const char *src)
+ * \brief Copy a string to another
+ */
+EXPORT char *strcpy(char *dst, const char *src)
+{
+ char *_dst = dst;
+ while(*src) {
+ *dst = *src;
+ src++; dst++;
+ }
+ *dst = '\0';
+ return _dst;
+}
+
+/**
+ * \fn EXPORT int strlen(const char *str)
+ * \brief Get the length of a string
+ */
+EXPORT int strlen(const char *str)
+{
+ int retval;
+ for(retval = 0; *str != '\0'; str++)
+ retval++;
+ return retval;
+}
+
+/**
+ * \fn EXPORT int strncmp(const char *s1, const char *s2, size_t len)
+ * \brief Compare two strings with a limit
+ */
+EXPORT int strncmp(const char *s1, const char *s2, size_t len)
+{
+ while(--len && *s1 == *s2 && *s1 != '\0' && *s2 != '\0') {
+ s1++; s2++;
+ }
+ return (int)*s1 - (int)*s2;
+}
+
+/**
+ * \fn EXPORT char *strdup(const char *str)
+ * \brief Duplicate a string using heap memory
+ * \note Defined in POSIX Spec, not C spec
+ */
+EXPORT char *strdup(const char *str)
+{
+ size_t len = strlen(str);
+ char *ret = malloc(len+1);
+ if(ret == NULL) return NULL;
+ strcpy(ret, str);
+ return ret;
+}
+
+// --- Memory ---
+/**
+ * \fn EXPORT void *memset(void *dest, int val, size_t num)
+ * \brief Clear memory with the specified value
+ */
+EXPORT void *memset(void *dest, int val, size_t num)
+{
+ unsigned char *p = dest;
+ while(num--) *p++ = val;
+ return dest;
+}
+
+/**
+ * \fn EXPORT void *memcpy(void *dest, const void *src, size_t count)
+ * \brief Copy one memory area to another
+ */
+EXPORT void *memcpy(void *dest, const void *src, size_t count)
+{
+ char *sp = (char *)src;
+ char *dp = (char *)dest;
+ for(;count--;) *dp++ = *sp++;
+ return dest;
+}
+
+/**
+ * \fn EXPORT void *memmove(void *dest, const void *src, size_t count)
+ * \brief Copy data in memory, avoiding overlap problems
+ */
+EXPORT void *memmove(void *dest, const void *src, size_t count)
+{
+ char *sp = (char *)src;
+ char *dp = (char *)dest;
+ // Check if corruption will happen
+ if( (unsigned int)dest > (unsigned int)src && (unsigned int)dest < (unsigned int)src+count )
+ for(;count--;) dp[count] = sp[count];
+ else
+ for(;count--;) *dp++ = *sp++;
+ return dest;
+}
--- /dev/null
+#
+# libgcc
+#
+
+-include ../Makefile.cfg
+
+OBJS = libgcc.o
+BIN = ../libgcc.so
+
+CFLAGS += -Wall -Werror
+LDFLAGS += -soname libgcc.acess.so
+
+.PHONY: all clean
+
+all: $(BIN)
+
+clean:
+ $(RM) $(BIN) $(OBJS)
+
+$(BIN): $(OBJS)
+ @echo -- ld -o $@
+ @$(LD) $(LDFLAGS) -o $(BIN) $(OBJS)
+ @$(OBJDUMP) -d $(BIN) > libgcc.so.dsm
+ cp $(BIN) $(DISTROOT)/Libs
+
+$(OBJS): %.o: %.c
+ @echo -- gcc -o $@
+ @$(CC) $(CFLAGS) -o $@ -c $<
--- /dev/null
+/* Acess GCC Helper Library
+ *
+ */
+#include <sys/sys.h>
+
+typedef unsigned long long int uint64_t;
+
+// === CODE ===
+int SoMain()
+{
+ return 0;
+}
+
+// --- Errors ---
+void __stack_chk_fail()
+{
+ write(1, 32, "FATAL ERROR: Stack Check Failed\n");
+ _exit(-1);
+ for(;;);
+}
+
+// --- 64-Bit Math ---
+/**
+ * \fn uint64_t __udivdi3(uint64_t Num, uint64_t Den)
+ * \brief Divide two 64-bit integers
+ */
+uint64_t __udivdi3(uint64_t Num, uint64_t Den)
+{
+ uint64_t ret = 0;
+ if(Den == 0) // Call Div by Zero Error
+ __asm__ __volatile__ ("int $0");
+ while(Num > Den) {
+ ret ++;
+ Num -= Den;
+ }
+ return ret;
+}
+
+/**
+ * \fn uint64_t __umoddi3(uint64_t Num, uint64_t Den)
+ * \brief Get the modulus of two 64-bit integers
+ */
+uint64_t __umoddi3(uint64_t Num, uint64_t Den)
+{
+ if(Den == 0) // Call Div by Zero Error
+ __asm__ __volatile__ ("int $0");
+ while(Num > Den)
+ Num -= Den;
+ return Num;
+}
--- /dev/null
+/*
+ * AcessOS LibC
+ * string.h
+ */
+#ifndef __STRING_H
+#define __STRING_H
+
+// Memory
+extern void *memset(void *dest, int val, size_t count);
+extern void *memcpy(void *dest, const void *src, size_t count);
+extern void *memmove(void *dest, const void *src, size_t count);
+extern int memcmp(const void *mem1, const void *mem2, size_t count);
+
+// Strings
+extern int strlen(const char *string);
+extern int strcmp(const char *str1, const char *str2);
+extern int strncmp(const char *str1, const char *str2, size_t len);
+extern char *strcpy(char *dst, const char *src);
+extern char *strdup(const char *src);
+
+#endif