From 9d3800f60f2212432e550a4e003ae65b498a4d36 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Fri, 2 Oct 2009 21:00:47 +0800 Subject: [PATCH] Cleanup - Unified the build systems for user and kernel space code - Fixed bug in VFS when VFS_Open is called by user when the current working directory is NULL - Added testing EXT2 and NE2000 drivers - Added files forgotten in the FDD commit --- Kernel/Makefile | 8 +- Kernel/Makefile.cfg | 6 - Kernel/arch/x86/Makefile | 8 +- Kernel/arch/x86/errors.c | 61 ++ Kernel/arch/x86/mm_virt.c | 7 +- Kernel/arch/x86/proc.c | 37 +- Kernel/binary.c | 4 +- Kernel/debug.c | 1 - Kernel/drv/ne2000.c | 213 +++++++ Kernel/include/common.h | 13 +- Kernel/include/dma.h | 10 + Kernel/include/signal.h | 16 + Kernel/include/threads.h | 6 +- Kernel/syscalls.c | 5 + Kernel/system.c | 1 - Kernel/threads.c | 96 ++- Kernel/vfs/fs/ext2.c | 584 ++++++++++++++++++ Kernel/vfs/fs/fs_ext2.h | 154 +++++ Kernel/vfs/open.c | 12 +- Makefile.cfg | 15 + README | 31 + Usermode/Applications/CLIShell_src/Makefile | 33 +- Usermode/Applications/Makefile.cfg | 9 + Usermode/Applications/cat_src/Makefile | 14 +- Usermode/Applications/init_src/Makefile | 21 +- Usermode/Applications/login_src/Makefile | 28 +- Usermode/Applications/login_src/header.h | 25 + Usermode/Applications/ls_src/Makefile | 27 + Usermode/Applications/ls_src/main.c | 165 +++++ Usermode/Libraries/Makefile.cfg | 9 + Usermode/Libraries/ld-acess.so_src/Makefile | 26 +- .../Libraries/ld-acess.so_src/helpers.asm | 58 ++ Usermode/Libraries/ld-acess.so_src/link.ld | 27 + Usermode/Libraries/libacess.so_src/Makefile | 13 +- Usermode/Libraries/libc.so_src/Makefile | 22 +- Usermode/Libraries/libc.so_src/config.h | 17 + Usermode/Libraries/libc.so_src/crt0.asm | 9 + Usermode/Libraries/libc.so_src/lib.h | 19 + Usermode/Libraries/libc.so_src/stdio_int.h | 31 + Usermode/Libraries/libc.so_src/string.c | 113 ++++ Usermode/Libraries/libgcc.so_src/Makefile | 28 + Usermode/Libraries/libgcc.so_src/libgcc.c | 50 ++ Usermode/include/string.h | 21 + 43 files changed, 1899 insertions(+), 154 deletions(-) delete mode 100644 Kernel/Makefile.cfg create mode 100644 Kernel/drv/ne2000.c create mode 100644 Kernel/include/dma.h create mode 100644 Kernel/include/signal.h create mode 100644 Kernel/vfs/fs/ext2.c create mode 100644 Kernel/vfs/fs/fs_ext2.h create mode 100644 Makefile.cfg create mode 100644 README create mode 100644 Usermode/Applications/Makefile.cfg create mode 100644 Usermode/Applications/login_src/header.h create mode 100644 Usermode/Applications/ls_src/Makefile create mode 100644 Usermode/Applications/ls_src/main.c create mode 100644 Usermode/Libraries/Makefile.cfg create mode 100644 Usermode/Libraries/ld-acess.so_src/helpers.asm create mode 100644 Usermode/Libraries/ld-acess.so_src/link.ld create mode 100644 Usermode/Libraries/libc.so_src/config.h create mode 100644 Usermode/Libraries/libc.so_src/crt0.asm create mode 100644 Usermode/Libraries/libc.so_src/lib.h create mode 100644 Usermode/Libraries/libc.so_src/stdio_int.h create mode 100644 Usermode/Libraries/libc.so_src/string.c create mode 100644 Usermode/Libraries/libgcc.so_src/Makefile create mode 100644 Usermode/Libraries/libgcc.so_src/libgcc.c create mode 100644 Usermode/include/string.h diff --git a/Kernel/Makefile b/Kernel/Makefile index e1534834..ae42dce5 100644 --- a/Kernel/Makefile +++ b/Kernel/Makefile @@ -4,12 +4,10 @@ # - The built objects and dependency files are suffixed with the arch name # - The final binary is Acess2..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) @@ -43,9 +41,9 @@ $(BIN): $(OBJ) arch/$(ARCHDIR)/link.ld Makefile @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 $@ diff --git a/Kernel/Makefile.cfg b/Kernel/Makefile.cfg deleted file mode 100644 index 8e186b82..00000000 --- a/Kernel/Makefile.cfg +++ /dev/null @@ -1,6 +0,0 @@ -# -# Acess2 Makefile Config -# Makefile.cfg - -ARCH = i386 -ARCHDIR = x86 diff --git a/Kernel/arch/x86/Makefile b/Kernel/arch/x86/Makefile index 335d2195..051d126e 100644 --- a/Kernel/arch/x86/Makefile +++ b/Kernel/arch/x86/Makefile @@ -4,10 +4,10 @@ # 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 = diff --git a/Kernel/arch/x86/errors.c b/Kernel/arch/x86/errors.c index 2c3582cd..0c2da16e 100644 --- a/Kernel/arch/x86/errors.c +++ b/Kernel/arch/x86/errors.c @@ -5,10 +5,16 @@ */ #include +// === 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) @@ -45,8 +51,63 @@ 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"); +} diff --git a/Kernel/arch/x86/mm_virt.c b/Kernel/arch/x86/mm_virt.c index 2b7d191b..3663d603 100644 --- a/Kernel/arch/x86/mm_virt.c +++ b/Kernel/arch/x86/mm_virt.c @@ -41,6 +41,7 @@ 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(); @@ -145,12 +146,14 @@ void MM_PageFault(Uint Addr, Uint ErrorCode, tRegs *Regs) ); } + 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); diff --git a/Kernel/arch/x86/proc.c b/Kernel/arch/x86/proc.c index 5cfc7a2e..f7bda0fc 100644 --- a/Kernel/arch/x86/proc.c +++ b/Kernel/arch/x86/proc.c @@ -33,6 +33,7 @@ extern tThread *gSleepingThreads; 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(); @@ -242,24 +243,19 @@ int Proc_Clone(Uint *Err, Uint Flags) __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 @@ -285,23 +281,6 @@ int Proc_Clone(Uint *Err, Uint Flags) *(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; @@ -318,8 +297,6 @@ int Proc_Clone(Uint *Err, Uint Flags) // Lock list and add to active Threads_AddActive(newThread); - //Threads_Dump(); - return newThread->TID; } diff --git a/Kernel/binary.c b/Kernel/binary.c index 1884af8a..dae3cfaa 100644 --- a/Kernel/binary.c +++ b/Kernel/binary.c @@ -25,8 +25,8 @@ typedef struct sKernelBin { extern int Proc_Clone(Uint *Err, Uint Flags); extern void Threads_SetName(char *Name); extern char *Threads_GetName(int ID); +extern void Threads_Exit(int, int); extern Uint MM_ClearUser(); -extern void Threads_Exit(); extern void Proc_StartUser(Uint Entrypoint, Uint *Bases, int ArgC, char **ArgV, char **EnvP, int DataSize); extern tKernelSymbol gKernelSymbols[]; extern void gKernelSymbolsEnd; @@ -147,7 +147,7 @@ int Proc_Execve(char *File, char **ArgV, char **EnvP) if(bases[0] == 0) { Warning("Proc_Execve - Unable to load '%s'", Threads_GetName(-1)); - Threads_Exit(); + Threads_Exit(0, 0); for(;;); } diff --git a/Kernel/debug.c b/Kernel/debug.c index bd3b4074..bf2282ff 100644 --- a/Kernel/debug.c +++ b/Kernel/debug.c @@ -314,7 +314,6 @@ void Debug_HexDump(char *Header, void *Data, Uint Length) cdat --; } E9('\n'); - } // --- EXPORTS --- diff --git a/Kernel/drv/ne2000.c b/Kernel/drv/ne2000.c new file mode 100644 index 00000000..e1f5990b --- /dev/null +++ b/Kernel/drv/ne2000.c @@ -0,0 +1,213 @@ +/* Acess2 + * NE2000 Driver + * + * See: ~/Sources/bochs/bochs.../iodev/ne2k.cc + */ +#include +#include +#include + +// === 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) +{ + +} diff --git a/Kernel/include/common.h b/Kernel/include/common.h index 7bf59382..590295f5 100644 --- a/Kernel/include/common.h +++ b/Kernel/include/common.h @@ -10,13 +10,19 @@ #include #include +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 -- @@ -43,6 +49,7 @@ extern void Panic(char *Msg, ...); 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, ...); @@ -114,10 +121,10 @@ extern int Proc_Spawn(char *Path); 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 #include diff --git a/Kernel/include/dma.h b/Kernel/include/dma.h new file mode 100644 index 00000000..5b0bbda2 --- /dev/null +++ b/Kernel/include/dma.h @@ -0,0 +1,10 @@ +/* + * 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 diff --git a/Kernel/include/signal.h b/Kernel/include/signal.h new file mode 100644 index 00000000..d97d6dcb --- /dev/null +++ b/Kernel/include/signal.h @@ -0,0 +1,16 @@ +/* + * Acess2 Kernel + * Signal List + */ +#ifndef _SIGNAL_H_ +#define _SIGNAL_H_ + +enum eSignals { + SIGKILL, + SIGSTOP, + SIGCONT, + SIGCHLD, + NSIG +}; + +#endif diff --git a/Kernel/include/threads.h b/Kernel/include/threads.h index 377b6ac1..1e15547c 100644 --- a/Kernel/include/threads.h +++ b/Kernel/include/threads.h @@ -16,6 +16,7 @@ typedef struct sMessage typedef struct sThread { + // --- threads.c's struct sThread *Next; //!< Next thread in list int IsLocked; //!< Thread's spinlock int Status; //!< Thread Status @@ -27,7 +28,9 @@ typedef struct sThread 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; @@ -35,6 +38,7 @@ typedef struct sThread //! 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 diff --git a/Kernel/syscalls.c b/Kernel/syscalls.c index dd1f4b3a..5774dbe5 100644 --- a/Kernel/syscalls.c +++ b/Kernel/syscalls.c @@ -119,6 +119,11 @@ void SyscallHandler(tSyscallRegs *Regs) // 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: diff --git a/Kernel/system.c b/Kernel/system.c index 26ce100e..9b160d92 100644 --- a/Kernel/system.c +++ b/Kernel/system.c @@ -19,7 +19,6 @@ void System_ExecuteScript(); int System_Int_GetString(char *Str, char **Dest); // === GLOBALS === -char *gsInitPath = "/Acess/Bin/init"; char *gsConfigScript = "/Acess/Conf/BootConf.cfg"; // === CODE === diff --git a/Kernel/threads.c b/Kernel/threads.c index 54438c32..5f2e3d7f 100644 --- a/Kernel/threads.c +++ b/Kernel/threads.c @@ -5,11 +5,17 @@ */ #include #include +#include // === 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(); @@ -22,6 +28,7 @@ void Threads_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); @@ -148,6 +155,88 @@ void Threads_SetTickets(int Num) 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 @@ -408,7 +497,7 @@ void Threads_Sleep() } -/** +/**c0108919: * \fn void Threads_Wake( tThread *Thread ) * \brief Wakes a sleeping/waiting thread up */ @@ -559,9 +648,10 @@ tThread *Threads_GetNextToRun(int CPU) int ticket; int number; + if(giNumActiveThreads == 0) return NULL; + // Special case: 1 thread - if(giNumActiveThreads == 1) - { + if(giNumActiveThreads == 1) { return gActiveThreads; } diff --git a/Kernel/vfs/fs/ext2.c b/Kernel/vfs/fs/ext2.c new file mode 100644 index 00000000..78c115ed --- /dev/null +++ b/Kernel/vfs/fs/ext2.c @@ -0,0 +1,584 @@ +/* + * Acess OS + * Ext2 Driver Version 1 + */ +/** + * \file fs/ext2.c + * \brief Second Extended Filesystem Driver + * \todo Implement file read support + */ +#include +#include +#include "fs_ext2.h" + +// === STRUCTURES === +typedef struct { + int FD; + int CacheID; + vfs_node RootNode; + + tExt2_SuperBlock SuperBlock; + int BlockSize; + + int GroupCount; + tExt2_Group Groups[]; +} tExt2_Disk; + +// === PROTOTYPES === +//Interface Functions +tVFS_Node *Ext2_InitDevice(char *Device, char **Options); +void Ext2_UnMount(tVFS_Node *Node); +Uint64 Ext2_Read(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer); +Uint64 Ext2_Write(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer); +char *Ext2_ReadDir(tVFS_Node *Node, int Pos); +tVFS_Node *Ext2_FindDir(tVFS_Node *Node, char *FileName); +tVFS_Node *Ext2_MkNod(tVFS_Node *Node, char *Name, Uint Flags); + int Ext2_int_GetInode(vfs_node *Node, tExt2_Inode *Inode); +tVFS_Node *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeId, char *Name, Uint64 VfsInode); + int Ext2_int_ReadInode(tExt2_Disk *Disk, Uint InodeId, tExt2_Inode *Inode); +Uint64 Ext2_int_GetBlockAddr(tExt2_Disk *Disk, Uint32 *Blocks, int BlockNum); + +// === SEMI-GLOBALS === +tExt2_Disk gExt2_disks[6]; + int giExt2_count = 0; +tVFS_Driver gExt2_FSInfo = {NULL, + "ext2", 0, Ext2_InitDevice, Ext2_UnMount, NULL + }; + +// === CODE === + +/** + * \fn void Ext2_Install() + * \brief Install the Ext2 Filesystem Driver + */ +void Ext2_Install() +{ + VFS_AddDriver( &gExt2_FSInfo ); +} + +/** + \fn tVFS_Node *Ext2_initDevice(char *Device, char **Options) + \brief Initializes a device to be read by by the driver + \param Device String - Device to read from + \param Options NULL Terminated array of option strings + \return Root Node +*/ +tVFS_Node *Ext2_InitDevice(char *Device, char **Options) +{ + tExt2_Disk *disk; + int fd; + int groupCount; + tExt2_SuperBlock sb; + tExt2_Inode inode; + + // Open Disk + fd = VFS_Open(Device, VFS_OPENFLAG_READ|VFS_OPENFLAG_WRITE); //Open Device + if(fd == -1) { + Warning"[EXT2] Unable to open '%s'\n", Device); + return NULL; + } + + // Read Superblock at offset 1024 + VFS_ReadAt(fd, 1024, 1024, &sb); // Read Superblock + + // Sanity Check Magic value + if(sb.s_magic != 0xEF53) { + WarningEx("EXT2", "Volume '%s' is not an EXT2 volume\n", Device); + VFS_Close(fd); + return NULL; + } + + // Get Group count + groupCount = DivUp(sb.s_blocks_count, sb.s_blocks_per_group); + //LogF(" Ext2_initDevice: groupCount = %i\n", groupCount); + + // Allocate Disk Information + disk = malloc(sizeof(tExt2_Disk) + sizeof(tExt2_Group)*groupCount); + disk->fd = fd; + memcpy(&disk->SuperBlock, &sb, 1024); + disk->GroupCount = groupCount; + + // Get an inode cache handle + disk->CacheID = Inode_GetHandle(); + + // Get Block Size + //LogF(" Ext2_initDevice: s_log_block_size = 0x%x\n", sb.s_log_block_size); + disk->BlockSize = 1024 << sb.s_log_block_size; + + // Read Group Information + VFS_ReadAt(disk->fd, + sb.s_first_data_block * disk->BlockSize + 1024, + sizeof(tExt2_Group)*groupCount, + disk->Groups); + + #if 0 + Log(" Ext2_initDevice: Block Group 0\n"); + Log(" Ext2_initDevice: .bg_block_bitmap = 0x%x\n", disk->Groups[0].bg_block_bitmap); + Log(" Ext2_initDevice: .bg_inode_bitmap = 0x%x\n", disk->Groups[0].bg_inode_bitmap); + Log(" Ext2_initDevice: .bg_inode_table = 0x%x\n", disk->Groups[0].bg_inode_table); + Log(" Ext2_initDevice: Block Group 1\n"); + Log(" Ext2_initDevice: .bg_block_bitmap = 0x%x\n", disk->Groups[1].bg_block_bitmap); + Log(" Ext2_initDevice: .bg_inode_bitmap = 0x%x\n", disk->Groups[1].bg_inode_bitmap); + Log(" Ext2_initDevice: .bg_inode_table = 0x%x\n", disk->Groups[1].bg_inode_table); + #endif + + // Get root Inode + Ext2_int_ReadInode(disk, 2, &inode); + + // Create Root Node + memset(&disk->RootNode, 0, sizeof(vfs_node)); + disk->RootNode.Inode = 2; // Root inode ID + disk->RootNode.ImplPtr = disk; // Save disk pointer + disk->RootNode.Size = -1; // Fill in later (on readdir) + disk->RootNode.Flags = VFS_FFLAG_DIRECTORY; + + disk->RootNode.ReadDir = Ext2_ReadDir; + disk->RootNode.FindDir = Ext2_FindDir; + //disk->RootNode.Relink = Ext2_Relink; + + // Complete root node + disk->RootNode.UID = inode.i_uid; + disk->RootNode.GID = inode.i_gid; + disk->RootNode.NumACLs = 1; + disk->RootNode.ACLs = &gVFS_ACL_EveryoneRW; + + #if 0 + Log(" Ext2_InitDevice: inode.i_size = 0x%x\n", inode.i_size); + Log(" Ext2_InitDevice: inode.i_block[0] = 0x%x\n", inode.i_block[0]); + #endif + + return &disk->RootNode; +} + +/** + * \fn void Ext2_Unmount(tVFS_Node *Node) + * \brief Close a mounted device + */ +void Ext2_Unmount(tVFS_Node *Node) +{ + tExt2_Disk *disk = Node->ImplPtr; + + VFS_Close( disk->fd ); + Inode_ClearCache( disk->CacheID ); + memset(disk, 0, sizeof(tExt2_Disk)+disk->GroupCount*sizeof(tExt2_Group)); + free(disk); +} + +/** + * \fn Uint64 Ext2_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) + * \brief Read from a file + */ +Uint64 Ext2_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) +{ + tExt2_Disk *disk = Node->ImplPtr; + tExt2_Inode inode; + Uint64 base; + Uint block; + Uint64 remLen; + + // Get Inode + Ext2_int_GetInode(Node, &inode); + + block = Offset / disk->BlockSize; + Offset = Offset / disk->BlockSize; + base = Ext2_int_GetBlockAddr(disk, inode.i_block, block); + + // Read only block + if(Length <= disk->BlockSize - Offset) + { + VFS_ReadAt( disk->fd, base+Offset, Length, Buffer); + 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); + 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); + + return Length; +} + +/** + * \fn Uint64 Ext2_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) + * \brief Write to a file + */ +Uint64 Ext2_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) +{ + tExt2_Disk *disk = Node->ImplPtr; + tExt2_Inode inode; + Uint64 base; + Uint64 retLen; + Uint block; + Uint64 allocSize; + int bNewBlocks = 0; + + Ext2_int_GetInode(Node, &inode); + + // 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); + if( Offset < allocSize ) + { + 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 + WarningEx("EXT2", "File extending is not yet supported"); + + return 0; +} + +/** + * \fn int Ext2_CloseFile(vfs_node *Node) + * \brief Close a file (Remove it from the cache) + */ +int Ext2_CloseFile(tVFS_Node *Node) +{ + tExt2_Disk *disk = Node->ImplPtr; + inode_uncacheNode(disk->CacheID, Node->impl); + return 1; +} + +/** + \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; + Uint64 vfsInode = 0; + tVFS_Node *retNode; + 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\n", 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 ('%s') extends over a block boundary, ignoring\n", + entNum-1, Node->impl, Node->name); + } + ofs = 0; + Base = Ext2_int_GetBlockAddr( disk, inode.i_block, block ); + } + } + + if(size <= 0) return NULL; + + // Read Entry + VFS_ReadAt( disk->fd, Base+ofs, sizeof(tExt2_DirEnt), &dirent ); + //LOG(" Ext2_ReadDir: dirent.inode = %i\n", dirent.inode); + //LOG(" Ext2_ReadDir: dirent.rec_len = %i\n", dirent.rec_len); + //LOG(" Ext2_ReadDir: dirent.name_len = %i\n", 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 ) { + Warnin("[EXT2 ] Directory Entry %i of inode %i ('%s') extends over a block boundary, ignoring\n", + entNum-1, Node->impl, Node->name); + } + ofs = 0; + Base = Ext2_int_GetBlockAddr( disk, inode.i_block, block ); + } + } + + return NULL; +} + +/** + * \fn tVFS_Node *Ext2_MkNod(tVFS_Node *Parent, char *Name, int Flags) + * \brief Create a new node + */ +tVFS_Node *Ext2_MkNod(tVFS_Node *Parent, char *Name, int Flags) +{ + return 0; +} + +//================================== +//= INTERNAL FUNCTIONS = +//================================== + + +/** + \internal + \fn int Ext2_int_GetInode(vfs_node *Node, tExt2_Inode *Inode) + \brief Gets the inode descriptor for a node + \param node node to get the Inode of + \param inode Destination +*/ +int Ext2_int_GetInode(tVFS_Node *Node, tExt2_Inode *Inode) +{ + return Ext2_int_ReadInode(Node->ImplPtr, Node->Inode, Inode); +} + +/** + * \fn vfs_node *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeID, char *Name) + * \brief Create a new VFS Node + */ +tVFS_Node *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeID, char *Name) +{ + tExt2_Inode inode; + tVFS_Node retNode; + tVFS_Node *tmpNode; + + if( !Ext2_int_ReadInode(Disk, InodeID, &inode) ) + return NULL; + + if( (tmpNode = inode_getCache(Disk->CacheID, InodeID)) ) + return tmpNode; + + + // Set identifiers + retNode.Inode = InodeID; + retNode.ImplPtr = Disk; + + // Set file length + retNode.Size = inode.i_size; + + // Set Access Permissions + retNode.UID = inode.i_uid; + retNode.GID = inode.i_gid; + retNode.NumACLs = 3; + retNode.ACLs = VFS_UnixToAcessACL(inode.i_mode & 0777, inode.i_uid, inode.i_gid); + + // Set Function Pointers + retNode.Read = Ext2_Read; + retNode.Write = Ext2_Write; + retNode.Close = Ext2_CloseFile; + + switch(inode.i_mode & EXT2_S_IFMT) + { + // Symbolic Link + case EXT2_S_IFLNK: + retNode.Flags = VFS_FFLAG_SYMLINK; + break; + // Regular File + case EXT2_S_IFREG: + retNode.flags = 0; + break; + // Directory + case EXT2_S_IFDIR: + retNode.ReadRir = Ext2_ReadDir; + retNode.FindDir = Ext2_FindDir; + retNode.MkNod = Ext2_MkNod; + //retNode.Relink = Ext2_Relink; + retNode.Flags = VFS_FFLAG_DIRECTORY; + break; + // Unknown, Write protect and hide it to be safe + default: + retNode.flags = VFS_FFLAG_READONLY|VFS_FFLAG_HIDDEN; + break; + } + + // Check if the file should be hidden + if(Name[0] == '.') retNode.Flags |= VFS_FFLAG_HIDDEN; + + // Set Timestamps + retNode.ATime = now(); + retNode.MTime = inode.i_mtime * 1000; + retNode.CTime = inode.i_ctime * 1000; + + // Save in node cache and return saved node + return Inode_CacheNode(Disk->CacheID, &retNode); +} + +/** + * \fn int Ext2_int_ReadInode(tExt2_Disk *Disk, Uint InodeId, tExt2_Inode *Inode) + * \brief Read an inode into memory + */ +int Ext2_int_ReadInode(tExt2_Disk *Disk, Uint InodeId, tExt2_Inode *Inode) +{ + int group, subId; + + //LogF("Ext2_int_ReadInode: (Disk=%p, InodeId=%i, Inode=%p)\n", Disk, InodeId, Inode); + + if(InodeId == 0) return 0; + + InodeId --; // Inodes are numbered starting at 1 + + group = InodeId / Disk->SuperBlock.s_inodes_per_group; + subId = InodeId % Disk->SuperBlock.s_inodes_per_group; + + //LogF(" Ext2_int_ReadInode: group=%i, subId = %i\n", group, subId); + + //Seek to Block - Absolute + vfs_seek(Disk->fd, Disk->Groups[group].bg_inode_table * Disk->BlockSize, SEEK_SET); + //Seeek to inode - Relative + vfs_seek(Disk->fd, sizeof(tExt2_Inode)*subId, SEEK_CUR); + vfs_read(Disk->fd, sizeof(tExt2_Inode), Inode); + return 1; +} + +/** + * \fn Uint64 Ext2_int_GetBlockAddr(tExt2_Disk *Disk, Uint32 *Blocks, int BlockNum) + * \brief Get the address of a block from an inode's list + * \param Disk Disk information structure + * \param Blocks Pointer to an inode's block list + * \param BlockNum Block index in list + */ +Uint64 Ext2_int_GetBlockAddr(tExt2_Disk *Disk, Uint32 *Blocks, int BlockNum) +{ + Uint32 *iBlocks; + // Direct Blocks + if(BlockNum < 12) + return (Uint64)Blocks[BlockNum] * Disk->BlockSize; + + // Single Indirect Blocks + iBlocks = malloc( Disk->BlockSize ); + VFS_ReadAt(Disk->fd, (Uint64)Blocks[12]*Disk->BlockSize, Disk->BlockSize, iBlocks); + + BlockNum -= 12; + if(BlockNum < 256) { + BlockNum = iBlocks[BlockNum]; + free(iBlocks); + return (Uint64)BlockNum * Disk->BlockSize; + } + + // Double Indirect Blocks + if(BlockNum < 256*256) + { + VFS_ReadAt(Disk->fd, (Uint64)Blocks[13]*Disk->BlockSize, Disk->BlockSize, iBlocks); + VFS_ReadAt(Disk->fd, (Uint64)iBlocks[BlockNum/256]*Disk->BlockSize, Disk->BlockSize, iBlocks); + BlockNum = iBlocks[BlockNum%256]; + free(iBlocks); + return (Uint64)BlockNum * Disk->BlockSize; + } + // Triple Indirect Blocks + VFS_ReadAt(Disk->fd, (Uint64)Blocks[14]*Disk->BlockSize, Disk->BlockSize, iBlocks); + VFS_ReadAt(Disk->fd, (Uint64)iBlocks[BlockNum/(256*256)]*Disk->BlockSize, Disk->BlockSize, iBlocks); + VFS_ReadAt(Disk->fd, (Uint64)iBlocks[(BlockNum/256)%256]*Disk->BlockSize, Disk->BlockSize, iBlocks); + BlockNum = iBlocks[BlockNum%256]; + free(iBlocks); + return (Uint64)BlockNum * Disk->BlockSize; +} diff --git a/Kernel/vfs/fs/fs_ext2.h b/Kernel/vfs/fs/fs_ext2.h new file mode 100644 index 00000000..9f84673b --- /dev/null +++ b/Kernel/vfs/fs/fs_ext2.h @@ -0,0 +1,154 @@ +/** + Acess Version 1 + \file fs_ext2_int.h + \brief EXT2 Filesystem Driver +*/ + +/** + \name Inode Flag Values + \{ +*/ +#define EXT2_S_IFMT 0xF000 //!< Format Mask +#define EXT2_S_IFSOCK 0xC000 //!< Socket +#define EXT2_S_IFLNK 0xA000 //!< Symbolic Link +#define EXT2_S_IFREG 0x8000 //!< Regular File +#define EXT2_S_IFBLK 0x6000 //!< Block Device +#define EXT2_S_IFDIR 0x4000 //!< Directory +#define EXT2_S_IFCHR 0x2000 //!< Character Device +#define EXT2_S_IFIFO 0x1000 //!< FIFO +#define EXT2_S_ISUID 0x0800 //!< SUID +#define EXT2_S_ISGID 0x0400 //!< SGID +#define EXT2_S_ISVTX 0x0200 //!< sticky bit +#define EXT2_S_IRWXU 0700 //!< user access rights mask +#define EXT2_S_IRUSR 0400 //!< Owner Read +#define EXT2_S_IWUSR 0200 //!< Owner Write +#define EXT2_S_IXUSR 0100 //!< Owner Execute +#define EXT2_S_IRWXG 0070 //!< Group Access rights mask +#define EXT2_S_IRGRP 0040 //!< Group Read +#define EXT2_S_IWGRP 0020 //!< Group Write +#define EXT2_S_IXGRP 0010 //!< Group Execute +#define EXT2_S_IRWXO 0007 //!< Global Access rights mask +#define EXT2_S_IROTH 0004 //!< Global Read +#define EXT2_S_IWOTH 0002 //!< Global Write +#define EXT2_S_IXOTH 0001 //!< Global Execute +//! \} + +#define EXT2_NAME_LEN 255 //!< Maximum Name Length + +//STRUCTURES +/** + \struct ext2_super_block_s + \brief EXT2 Superblock Structure +*/ +struct ext2_super_block_s { + Uint32 s_inodes_count; //!< Inodes count + Uint32 s_blocks_count; //!< Blocks count + Uint32 s_r_blocks_count; //!< Reserved blocks count + Uint32 s_free_blocks_count; //!< Free blocks count + Uint32 s_free_inodes_count; //!< Free inodes count + Uint32 s_first_data_block; //!< First Data Block + Uint32 s_log_block_size; //!< Block size + Sint32 s_log_frag_size; //!< Fragment size + Uint32 s_blocks_per_group; //!< Number Blocks per group + Uint32 s_frags_per_group; //!< Number Fragments per group + Uint32 s_inodes_per_group; //!< Number Inodes per group + Uint32 s_mtime; //!< Mount time + Uint32 s_wtime; //!< Write time + Uint16 s_mnt_count; //!< Mount count + Sint16 s_max_mnt_count; //!< Maximal mount count + Uint16 s_magic; //!< Magic signature + Uint16 s_state; //!< File system state + Uint16 s_errors; //!< Behaviour when detecting errors + Uint16 s_pad; //!< Padding + Uint32 s_lastcheck; //!< time of last check + Uint32 s_checkinterval; //!< max. time between checks + Uint32 s_creator_os; //!< Formatting OS + Uint32 s_rev_level; //!< Revision level + Uint16 s_def_resuid; //!< Default uid for reserved blocks + Uint16 s_def_resgid; //!< Default gid for reserved blocks + Uint32 s_reserved[235]; //!< Padding to the end of the block +}; + +/** + \struct ext2_inode_s + \brief EXT2 Inode Definition +*/ +struct ext2_inode_s { + Uint16 i_mode; //!< File mode + Uint16 i_uid; //!< Owner Uid + Uint32 i_size; //!< Size in bytes + Uint32 i_atime; //!< Access time + Uint32 i_ctime; //!< Creation time + Uint32 i_mtime; //!< Modification time + Uint32 i_dtime; //!< Deletion Time + Uint16 i_gid; //!< Group Id + Uint16 i_links_count; //!< Links count + Uint32 i_blocks; //!< Blocks count + Uint32 i_flags; //!< File flags + union { + Uint32 linux_reserved1; //!< Linux: Reserved + Uint32 hurd_translator; //!< HURD: Translator + Uint32 masix_reserved1; //!< Masix: Reserved + } osd1; //!< OS dependent 1 + Uint32 i_block[15]; //!< Pointers to blocks + Uint32 i_version; //!< File version (for NFS) + Uint32 i_file_acl; //!< File ACL + Uint32 i_dir_acl; //!< Directory ACL + Uint32 i_faddr; //!< Fragment address + union { + struct { + Uint8 l_i_frag; //!< Fragment number + Uint8 l_i_fsize; //!< Fragment size + Uint16 i_pad1; //!< Padding + Uint32 l_i_reserved2[2]; //!< Reserved + } linux2; + struct { + Uint8 h_i_frag; //!< Fragment number + Uint8 h_i_fsize; //!< Fragment size + Uint16 h_i_mode_high; //!< Mode High Bits + Uint16 h_i_uid_high; //!< UID High Bits + Uint16 h_i_gid_high; //!< GID High Bits + Uint32 h_i_author; //!< Creator ID + } hurd2; + struct { + Uint8 m_i_frag; //!< Fragment number + Uint8 m_i_fsize; //!< Fragment size + Uint16 m_pad1; //!< Padding + Uint32 m_i_reserved2[2]; //!< reserved + } masix2; + } osd2; //!< OS dependent 2 +}; + +/** + \struct ext2_group_desc_s + \brief EXT2 Group Descriptor +*/ +struct ext2_group_desc_s { + Uint32 bg_block_bitmap; //!< Blocks bitmap block + Uint32 bg_inode_bitmap; //!< Inodes bitmap block + Uint32 bg_inode_table; //!< Inodes table block + Uint16 bg_free_blocks_count; //!< Free blocks count + Uint16 bg_free_inodes_count; //!< Free inodes count + Uint16 bg_used_dirs_count; //!< Directories count + Uint16 bg_pad; //!< Padding + Uint32 bg_reserved[3]; //!< Reserved +}; + +/** + \struct ext2_dir_entry + \brief EXT2 Directory Entry + \note The name may take up less than 255 characters +*/ +struct ext2_dir_entry_s { + Uint32 inode; //!< Inode number + Uint16 rec_len; //!< Directory entry length + Uint8 name_len; //!< Short Name Length + Uint8 type; //!< File Type + char name[]; //!< File name +}; + +//TYPEDEFS +typedef struct ext2_inode_s tExt2_Inode; //!< Inode Type +typedef struct ext2_super_block_s tExt2_SuperBlock; //!< Superblock Type +typedef struct ext2_group_desc_s tExt2_Group; //!< Group Descriptor Type +typedef struct ext2_dir_entry_s tExt2_DirEnt; //!< Directory Entry Type diff --git a/Kernel/vfs/open.c b/Kernel/vfs/open.c index 0494294d..6f034170 100644 --- a/Kernel/vfs/open.c +++ b/Kernel/vfs/open.c @@ -61,7 +61,13 @@ char *VFS_GetAbsPath(char *Path) } 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); @@ -119,6 +125,7 @@ char *VFS_GetAbsPath(char *Path) 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); @@ -534,7 +541,8 @@ int VFS_ChDir(char *New) 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; diff --git a/Makefile.cfg b/Makefile.cfg new file mode 100644 index 00000000..65d3fa04 --- /dev/null +++ b/Makefile.cfg @@ -0,0 +1,15 @@ +# +# Acess2 Build Configuration +# + +CC = gcc +LD = ld +AS = nasm +OBJDUMP = objdump +RM = @rm -f +STRIP = strip + +ARCH = i386 +ARCHDIR = x86 + +DISTROOT = /mnt/AcessHDD/Acess2 diff --git a/README b/README new file mode 100644 index 00000000..66d70f1b --- /dev/null +++ b/README @@ -0,0 +1,31 @@ +======== + 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/ - 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 === diff --git a/Usermode/Applications/CLIShell_src/Makefile b/Usermode/Applications/CLIShell_src/Makefile index a79952e7..a87f3298 100644 --- a/Usermode/Applications/CLIShell_src/Makefile +++ b/Usermode/Applications/CLIShell_src/Makefile @@ -1,36 +1,27 @@ # Project: Acess Shell -CC = gcc -AS = nasm -LD = ld -RM = @rm -f +-include ../Makefile.cfg -COBJ = main.o lib.o -BIN = ../CLIShell -ACESSDIR = /home/hodgeja/Projects/Acess2/Usermode +CPPFLAGS += -I./include +CFLAGS += -Wall -fno-builtin -fno-stack-protector +LDFLAGS += -INCS = -I$(ACESSDIR)/include -I./include -CFLAGS = -Wall -fno-builtin -fno-stack-protector $(INCS) -ASFLAGS = -felf -LDFLAGS = -T $(ACESSDIR)/Libraries/acess.ld -I /Acess/Libs/ld-acess.so -lc +BIN = ../CLIShell +COBJ = main.o lib.o .PHONY : all clean all: $(BIN) -$(BIN): $(AOBJ) $(COBJ) +clean: + $(RM) $(COBJ) $(BIN) + +$(BIN): $(COBJ) @echo --- $(LD) -o $@ - @$(LD) $(LDFLAGS) -o $@ $(AOBJ) $(COBJ) -Map Map.txt + @$(LD) $(LDFLAGS) -o $@ $(COBJ) -Map Map.txt objdump -d $(BIN) > $(BIN).dsm - cp $(BIN) /mnt/AcessHDD/Acess2/Bin/ - -clean: - $(RM) $(AOBJ) $(COBJ) $(BIN) + cp $(BIN) $(DISTROOT)/Bin/ $(COBJ): %.o: %.c @echo --- GCC -o $@ @$(CC) $(CFLAGS) -c $? -o $@ - -$(AOBJ): %.ao: %.asm - @echo --- $(AS) -o $@ - @$(AS) $(ASFLAGS) -o $@ $< diff --git a/Usermode/Applications/Makefile.cfg b/Usermode/Applications/Makefile.cfg new file mode 100644 index 00000000..f8cd1515 --- /dev/null +++ b/Usermode/Applications/Makefile.cfg @@ -0,0 +1,9 @@ +# 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 diff --git a/Usermode/Applications/cat_src/Makefile b/Usermode/Applications/cat_src/Makefile index 5774e570..53b8edfe 100644 --- a/Usermode/Applications/cat_src/Makefile +++ b/Usermode/Applications/cat_src/Makefile @@ -1,18 +1,12 @@ # Project: cat -CC = gcc -AS = nasm -LD = ld -RM = @rm -f +-include ../Makefile.cfg COBJ = main.o BIN = ../cat -ACESSDIR = /home/hodgeja/Projects/Acess2/Usermode -INCS = -I$(ACESSDIR)/include -I./include -CFLAGS = -Wall -fno-builtin -fno-stack-protector $(INCS) -ASFLAGS = -felf -LDFLAGS = -T $(ACESSDIR)/Libraries/acess.ld -I /Acess/Libs/ld-acess.so -lc +CFLAGS += -Wall -fno-builtin -fno-stack-protector +LDFLAGS += .PHONY : all clean @@ -22,7 +16,7 @@ $(BIN): $(COBJ) @echo --- $(LD) -o $@ @$(LD) $(LDFLAGS) -o $@ $(COBJ) -Map Map.txt objdump -d $(BIN) > $(BIN).dsm - cp $(BIN) /mnt/AcessHDD/Acess2/Bin/ + cp $(BIN) $(DISTROOT)/Bin/ clean: $(RM) $(COBJ) $(BIN) diff --git a/Usermode/Applications/init_src/Makefile b/Usermode/Applications/init_src/Makefile index a51f61ba..0ec77391 100644 --- a/Usermode/Applications/init_src/Makefile +++ b/Usermode/Applications/init_src/Makefile @@ -1,27 +1,24 @@ # -# -# -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 $@ diff --git a/Usermode/Applications/login_src/Makefile b/Usermode/Applications/login_src/Makefile index 83d9d7a1..c09a174a 100644 --- a/Usermode/Applications/login_src/Makefile +++ b/Usermode/Applications/login_src/Makefile @@ -1,18 +1,12 @@ -# -# -# +# 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 @@ -25,9 +19,11 @@ clean: $(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 $@ diff --git a/Usermode/Applications/login_src/header.h b/Usermode/Applications/login_src/header.h new file mode 100644 index 00000000..695e1a9d --- /dev/null +++ b/Usermode/Applications/login_src/header.h @@ -0,0 +1,25 @@ +/* + * Acess2 Login Shell + */ +#ifndef _HEADER_H_ +#define _HEADER_H_ + +#include +#include +#include +#include + +// === 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 diff --git a/Usermode/Applications/ls_src/Makefile b/Usermode/Applications/ls_src/Makefile new file mode 100644 index 00000000..893dc556 --- /dev/null +++ b/Usermode/Applications/ls_src/Makefile @@ -0,0 +1,27 @@ +# Project: cat + +-include ../Makefile.cfg + +COBJ = main.o +BIN = ../ls + +CFLAGS += -Wall -fno-builtin +LDFLAGS += + +.PHONY : all clean + +all: $(BIN) + +$(BIN): $(COBJ) + @echo --- $(LD) -o $@ + @$(LD) $(LDFLAGS) -o $@ $(COBJ) -Map Map.txt + objdump -d $(BIN) > $(BIN).dsm + cp $(BIN) $(DISTROOT)/Bin/ + +clean: + $(RM) $(COBJ) $(BIN) + +$(COBJ): %.o: %.c + @echo --- GCC -o $@ + @$(CC) $(CFLAGS) -c $? -o $@ + diff --git a/Usermode/Applications/ls_src/main.c b/Usermode/Applications/ls_src/main.c new file mode 100644 index 00000000..82f9c2a6 --- /dev/null +++ b/Usermode/Applications/ls_src/main.c @@ -0,0 +1,165 @@ +/* + * Acess2 LS command + */ +#include +#include +#include +#include + +#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] []\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); +} diff --git a/Usermode/Libraries/Makefile.cfg b/Usermode/Libraries/Makefile.cfg new file mode 100644 index 00000000..2e09392f --- /dev/null +++ b/Usermode/Libraries/Makefile.cfg @@ -0,0 +1,9 @@ +# 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 diff --git a/Usermode/Libraries/ld-acess.so_src/Makefile b/Usermode/Libraries/ld-acess.so_src/Makefile index 2d005160..63490916 100644 --- a/Usermode/Libraries/ld-acess.so_src/Makefile +++ b/Usermode/Libraries/ld-acess.so_src/Makefile @@ -2,22 +2,15 @@ # LD-ACESS.SO # Makefile -CC = gcc -AS = nasm -RM = @rm -f -LD = ld -OBJDUMP = objdump +-include ../Makefile.cfg COBJ = main.o lib.o loadlib.o elf.o pe.o AOBJ = helpers.ao BIN = ../ld-acess.so -CPPFLAGS = -I../../include -CFLAGS = -Wall -fno-builtin -fleading-underscore -fno-stack-protector -ASFLAGS = -felf -#LDFLAGS = --oformat elf32-i386 -Map map.txt -Bstatic -e _SoMain -shared -#LDFLAGS = --oformat elf32-i386 -Map map.txt -Bstatic -e _SoMain -Ttext 0xBFFFE000 -LDFLAGS = -T link.ld -Map map.txt -Bstatic +CFLAGS = -Wall -fno-builtin -fleading-underscore -fno-stack-protector +ASFLAGS = -felf +LDFLAGS = -T link.ld -Map map.txt -Bstatic .PHONY: all clean @@ -28,14 +21,17 @@ clean: $(RM) $(BIN) $(AOBJ) $(COBJ) $(BIN): $(AOBJ) $(COBJ) - $(LD) $(LDFLAGS) -o $(BIN) $(AOBJ) $(COBJ) > link.txt + @echo --- $(LD) -shared -o $@ + @$(LD) $(LDFLAGS) -o $(BIN) $(AOBJ) $(COBJ) > link.txt $(OBJDUMP) -x $(BIN) > ld-acess.dmp $(OBJDUMP) -d $(BIN) > ld-acess.dsm - cp $(BIN) /mnt/AcessHDD/Acess2/Libs + cp $(BIN) $(DISTROOT)/Libs $(COBJ): %.o: %.c - $(CC) $(CFLAGS) -o $@ -c $< + @echo $(CC) -o $@ + @$(CC) $(CFLAGS) -o $@ -c $< $(AOBJ): %.ao: %.asm - $(AS) $(ASFLAGS) -o $@ $< + @echo $(AS) -o $@ + @$(AS) $(ASFLAGS) -o $@ $< diff --git a/Usermode/Libraries/ld-acess.so_src/helpers.asm b/Usermode/Libraries/ld-acess.so_src/helpers.asm new file mode 100644 index 00000000..eb275ee2 --- /dev/null +++ b/Usermode/Libraries/ld-acess.so_src/helpers.asm @@ -0,0 +1,58 @@ +; AcessOS 1 +; By thePowersGang +; LD-ACESS.SO +; - helpers.asm + +%include "../libacess.so_src/syscalls.inc.asm" + +[global _SysDebug] +[global _SysExit] +[global _SysLoadBin] +[global _SysUnloadBin] + +; void SysDebugV(char *fmt, va_list Args) +_SysDebug: + ;xchg bx, bx + push ebp + mov ebp, esp + pusha + + mov eax, 0x100 ; User Debug + mov ebx, [ebp+8] ; Format + mov ecx, [ebp+12] ; Arguments + mov edx, [ebp+16] ; Arguments + mov edi, [ebp+20] ; Arguments + mov esi, [ebp+24] ; Arguments + int 0xAC + + popa + pop ebp + ret + +; void SysExit() +_SysExit: + push ebx + mov eax, SYS_EXIT ; Exit + mov ebx, [esp+0x8] ; Exit Code + int 0xAC + pop ebx + ret + +; Uint SysLoadBin(char *path, Uint *entry) +_SysLoadBin: + push ebx + mov eax, SYS_LOADBIN ; SYS_LDBIN + mov ebx, [esp+0x8] ; Path + mov ecx, [esp+0xC] ; Entry + int 0xAC + pop ebx + ret + +; Uint SysUnloadBin(Uint Base) +_SysUnloadBin: + push ebx + mov eax, SYS_UNLOADBIN ; SYS_ULDBIN + mov ebx, [esp+0x8] ; Base + int 0xAC + pop ebx + ret diff --git a/Usermode/Libraries/ld-acess.so_src/link.ld b/Usermode/Libraries/ld-acess.so_src/link.ld new file mode 100644 index 00000000..8ddc2346 --- /dev/null +++ b/Usermode/Libraries/ld-acess.so_src/link.ld @@ -0,0 +1,27 @@ +ENTRY(_SoMain) +OUTPUT_FORMAT(elf32-i386) + +SECTIONS { + . = 0xBBFF0000; + _gLinkedBase = .; + + .text : AT(ADDR(.text)) { + code = .; + *(.text) + *(.rodata*) + } + + .data ALIGN (0x1000) : AT(ADDR(.data)) { + data = .; + *(.data) + } + + .bss ALIGN (0x1000) : AT(ADDR(.bss)) { + _sbss = .; + *(COMMON) + *(.bss) + _ebss = .; + bss = .; + } + _end = .; +} diff --git a/Usermode/Libraries/libacess.so_src/Makefile b/Usermode/Libraries/libacess.so_src/Makefile index 7b320b93..3118cb67 100644 --- a/Usermode/Libraries/libacess.so_src/Makefile +++ b/Usermode/Libraries/libacess.so_src/Makefile @@ -2,10 +2,7 @@ # # -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 @@ -21,9 +18,11 @@ clean: $(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 $@ $< diff --git a/Usermode/Libraries/libc.so_src/Makefile b/Usermode/Libraries/libc.so_src/Makefile index fd186a9d..c2979a07 100644 --- a/Usermode/Libraries/libc.so_src/Makefile +++ b/Usermode/Libraries/libc.so_src/Makefile @@ -1,19 +1,15 @@ -# AcessOS Basic C Library +# Acess2 Basic C Library # Makefile -CC = gcc -AS = nasm -RM = @rm -f -LD = ld -OBJDUMP = objdump -ACESSDIR = /home/hodgeja/Projects/Acess2 +-include ../Makefile.cfg -CPPFLAGS = -I$(ACESSDIR)/Usermode/include -CFLAGS = -Wall -fPIC -fno-builtin -fno-stack-protector $(CPPFLAGS) -ASFLAGS = -felf -LDFLAGS = -x -shared -soname libc.so.1 -Map map.txt -e SoMain -L$(ACESSDIR)/Usermode/Libraries -lacess +CPPFLAGS += +CFLAGS += +ASFLAGS += +LDFLAGS += -soname libc.so.1 -Map map.txt -OBJ_LIBC = heap.o stdlib.o stub.o env.o fileIO.o signals.o string.o +OBJ_LIBC = heap.o stdlib.o stub.o env.o fileIO.o string.o +# signals.o BIN = ../libc.so.1 .PHONY: all clean @@ -30,7 +26,7 @@ $(BIN): $(OBJ_LIBC) $(OBJDUMP) -d $@ > libc.so.1.dsm $(OBJDUMP) -x -r -R $@ > libc.so.1.dmp cp ../libc.so.1 ../libc.so - cp ../libc.so.1 /mnt/AcessHDD/Acess2/Libs/ + cp ../libc.so.1 $(DISTROOT)/Libs/ # C Runtime 0 ../crt0.o: crt0.asm diff --git a/Usermode/Libraries/libc.so_src/config.h b/Usermode/Libraries/libc.so_src/config.h new file mode 100644 index 00000000..fe3343ee --- /dev/null +++ b/Usermode/Libraries/libc.so_src/config.h @@ -0,0 +1,17 @@ +/* + * 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 diff --git a/Usermode/Libraries/libc.so_src/crt0.asm b/Usermode/Libraries/libc.so_src/crt0.asm new file mode 100644 index 00000000..e61a44c9 --- /dev/null +++ b/Usermode/Libraries/libc.so_src/crt0.asm @@ -0,0 +1,9 @@ +; AcessOS LibC +; crt0.asm +; + +[extern _heap_start] + +start: + + diff --git a/Usermode/Libraries/libc.so_src/lib.h b/Usermode/Libraries/libc.so_src/lib.h new file mode 100644 index 00000000..9d5194b1 --- /dev/null +++ b/Usermode/Libraries/libc.so_src/lib.h @@ -0,0 +1,19 @@ +/* +AcessOS Basic Lib C + +lib.h +*/ +#ifndef _LIB_H +#define _LIB_H + +#define BUILD_SO 1 + +#if defined(BUILD_DLL) +#define EXPORT __declspec(dllexport) +#define LOCAL +#elif defined(BUILD_SO) +#define EXPORT +#define LOCAL +#endif + +#endif diff --git a/Usermode/Libraries/libc.so_src/stdio_int.h b/Usermode/Libraries/libc.so_src/stdio_int.h new file mode 100644 index 00000000..5bfbf986 --- /dev/null +++ b/Usermode/Libraries/libc.so_src/stdio_int.h @@ -0,0 +1,31 @@ +/* + * 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 diff --git a/Usermode/Libraries/libc.so_src/string.c b/Usermode/Libraries/libc.so_src/string.c new file mode 100644 index 00000000..07c20179 --- /dev/null +++ b/Usermode/Libraries/libc.so_src/string.c @@ -0,0 +1,113 @@ +/* + * AcessOS Basic C Library + * string.c + */ +#include +#include +#include +#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; +} diff --git a/Usermode/Libraries/libgcc.so_src/Makefile b/Usermode/Libraries/libgcc.so_src/Makefile new file mode 100644 index 00000000..ada47db9 --- /dev/null +++ b/Usermode/Libraries/libgcc.so_src/Makefile @@ -0,0 +1,28 @@ +# +# 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 $< diff --git a/Usermode/Libraries/libgcc.so_src/libgcc.c b/Usermode/Libraries/libgcc.so_src/libgcc.c new file mode 100644 index 00000000..2127b551 --- /dev/null +++ b/Usermode/Libraries/libgcc.so_src/libgcc.c @@ -0,0 +1,50 @@ +/* Acess GCC Helper Library + * + */ +#include + +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; +} diff --git a/Usermode/include/string.h b/Usermode/include/string.h new file mode 100644 index 00000000..158aeeb7 --- /dev/null +++ b/Usermode/include/string.h @@ -0,0 +1,21 @@ +/* + * 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 -- 2.20.1