From 95a7eaaa4a1065334125b65130866f8d1048ddb7 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Mon, 26 Oct 2009 12:54:31 +0800 Subject: [PATCH 1/1] Fixes to Libc, Doxygen Comments and VTerm layout - Fixed Libc so that zlib could compile against it (still some bugs to get rid of) - Fixed doxygen commenting - Fixed a bug in the Makefile (used %* instead of $*) - Changed the structure of the VTerm driver to facilitate kernel modesetting properly --- Kernel/Makefile | 5 +- Kernel/arch/x86/lib.c | 6 +- Kernel/arch/x86/mm_virt.c | 2 +- Kernel/arch/x86/proc.c | 4 +- Kernel/arch/x86/time.c | 2 +- Kernel/debug.c | 18 +- Kernel/drv/kb.c | 54 +- Kernel/drv/kb_kbdus.h | 1 + Kernel/drv/vterm.c | 352 ++++++++++-- Kernel/include/modules.h | 5 +- Kernel/include/syscalls.h | 3 +- Kernel/include/syscalls.inc.asm | 1 + Kernel/include/tpl_drv_keyboard.h | 10 +- Kernel/include/tpl_drv_video.h | 15 +- Kernel/lib.c | 2 +- Kernel/messages.c | 5 + Kernel/proc.c | 653 ---------------------- Kernel/system.c | 4 + Kernel/threads.c | 5 +- Kernel/vfs.c | 12 - Kernel/vfs/fs/devfs.c | 2 +- Kernel/vfs/fs/ext2.c | 14 +- Kernel/vfs/fs/fat.c | 2 +- Kernel/vfs/fs/fs_ext2.h | 46 +- Makefile.cfg | 2 +- Modules/BochsVBE/bochsvbe.c | 14 +- Modules/Makefile.tpl | 12 +- Modules/NE2000/Makefile | 2 +- Usermode/Applications/CLIShell_src/main.c | 125 +++-- Usermode/Applications/init_src/main.c | 29 +- Usermode/Applications/login_src/main.c | 16 +- Usermode/Libraries/libc.so_src/fileIO.c | 10 +- Usermode/Libraries/libc.so_src/string.c | 112 ++++ Usermode/include/acess/sys.h | 8 +- Usermode/include/stdio.h | 14 +- Usermode/include/stdlib.h | 15 +- Usermode/include/string.h | 20 +- 37 files changed, 682 insertions(+), 920 deletions(-) delete mode 100644 Kernel/proc.c delete mode 100644 Kernel/vfs.c diff --git a/Kernel/Makefile b/Kernel/Makefile index 45d2f023..c538da54 100644 --- a/Kernel/Makefile +++ b/Kernel/Makefile @@ -24,7 +24,7 @@ OBJ += $(addprefix vfs/fs/, $(addsuffix .o,$(FILESYSTEMS))) OBJ += drv/fifo.o drv/dma.o drv/pci.o drv/vterm.o drv/vga.o drv/kb.o OBJ += $(addprefix drv/, $(addsuffix .o,$(DRIVERS))) OBJ := $(addsuffix .$(ARCH), $(OBJ)) -MODS += $(addprefix ../Modules/, $(addsuffix .o.$(ARCH),$(MODULES))) +MODS += $(addprefix ../Modules/, $(addsuffix .xo.$(ARCH),$(MODULES))) BIN = ../Acess2.$(ARCH).bin DEPFILES = $(filter %.o.$(ARCH),$(OBJ)) @@ -61,6 +61,9 @@ $(BIN): $(OBJ) $(MODS) arch/$(ARCHDIR)/link.ld Makefile @$(MAKEDEP) $(CPPFLAGS) -MT $@ -o $*.d.$(ARCH) $< # endif +%.xo.$(ARCH): + @make -C $* all + include/syscalls.h: syscalls.lst Makefile php GenSyscalls.php diff --git a/Kernel/arch/x86/lib.c b/Kernel/arch/x86/lib.c index 7e79c711..8b86145e 100644 --- a/Kernel/arch/x86/lib.c +++ b/Kernel/arch/x86/lib.c @@ -86,7 +86,8 @@ int memcmp(const void *m1, const void *m2, Uint Num) } /** - * \fn void *memcpy(void *Dest, void *Src, Uint Num) + * \fn void *memcpy(void *Dest, const void *Src, Uint Num) + * \brief Copy \a Num bytes from \a Src to \a Dest */ void *memcpy(void *Dest, const void *Src, Uint Num) { @@ -102,7 +103,8 @@ void *memcpy(void *Dest, const void *Src, Uint Num) return Dest; } /** - * \fn void *memcpyd(void *Dest, void *Src, Uint Num) + * \fn void *memcpyd(void *Dest, const void *Src, Uint Num) + * \brief Copy \a Num DWORDs from \a Src to \a Dest */ void *memcpyd(void *Dest, const void *Src, Uint Num) { diff --git a/Kernel/arch/x86/mm_virt.c b/Kernel/arch/x86/mm_virt.c index f5b89590..d7d1d81f 100644 --- a/Kernel/arch/x86/mm_virt.c +++ b/Kernel/arch/x86/mm_virt.c @@ -174,7 +174,7 @@ void MM_PageFault(Uint Addr, Uint ErrorCode, tRegs *Regs) } /** - * \fn void MM_DumpTables(Uint Start, Uint End) + * \fn void MM_DumpTables(tVAddr Start, tVAddr End) * \brief Dumps the layout of the page tables */ void MM_DumpTables(tVAddr Start, tVAddr End) diff --git a/Kernel/arch/x86/proc.c b/Kernel/arch/x86/proc.c index 5132f829..5301401e 100644 --- a/Kernel/arch/x86/proc.c +++ b/Kernel/arch/x86/proc.c @@ -386,7 +386,7 @@ Uint Proc_MakeUserStack() /** - * \fn void Proc_StartUser(Uint Entrypoint, Uint Base, int ArgC, char **ArgV, char **EnvP, int DataSize) + * \fn void Proc_StartUser(Uint Entrypoint, Uint *Bases, int ArgC, char **ArgV, char **EnvP, int DataSize) * \brief Starts a user task */ void Proc_StartUser(Uint Entrypoint, Uint *Bases, int ArgC, char **ArgV, char **EnvP, int DataSize) @@ -457,6 +457,8 @@ void Proc_StartUser(Uint Entrypoint, Uint *Bases, int ArgC, char **ArgV, char ** * \fn int Proc_Demote(Uint *Err, int Dest, tRegs *Regs) * \brief Demotes a process to a lower permission level * \param Err Pointer to user's errno + * \param Dest New Permission Level + * \param Regs Pointer to user's register structure */ int Proc_Demote(Uint *Err, int Dest, tRegs *Regs) { diff --git a/Kernel/arch/x86/time.c b/Kernel/arch/x86/time.c index 79ea4d08..cfe2f036 100644 --- a/Kernel/arch/x86/time.c +++ b/Kernel/arch/x86/time.c @@ -87,10 +87,10 @@ void Time_Interrupt() inb(0x71); // Just throw away contents. } +#if 0 /** * \fn void Time_TimerThread() */ -#if 0 void Time_TimerThread() { Sint64 next; diff --git a/Kernel/debug.c b/Kernel/debug.c index 99a236ec..72621cc3 100644 --- a/Kernel/debug.c +++ b/Kernel/debug.c @@ -5,16 +5,21 @@ #include #include -// === MACROS === -#define E9(ch) __asm__ __volatile__ ("outb %%al, $0xe9"::"a"(((Uint8)ch))) - // === IMPORTS === extern void Threads_Dump(); // === GLOBALS === int gDebug_Level = 0; + int giDebug_KTerm = -1; // === CODE === +static void E9(char ch) +{ + if(giDebug_KTerm != -1) + VFS_Write(giDebug_KTerm, 1, &ch); + __asm__ __volatile__ ( "outb %%al, $0xe9" :: "a"(((Uint8)ch)) ); +} + static void E9_Str(char *Str) { while(*Str) E9(*Str++); @@ -190,6 +195,13 @@ void Panic(char *Fmt, ...) for(;;) __asm__ __volatile__ ("hlt"); } +void Debug_SetKTerminal(char *File) +{ + if(giDebug_KTerm != -1) + VFS_Close(giDebug_KTerm); + giDebug_KTerm = VFS_Open(File, VFS_OPENFLAG_WRITE); +} + void Debug_Enter(char *FuncName, char *ArgTypes, ...) { va_list args; diff --git a/Kernel/drv/kb.c b/Kernel/drv/kb.c index d6124e7f..608b058a 100644 --- a/Kernel/drv/kb.c +++ b/Kernel/drv/kb.c @@ -29,8 +29,8 @@ tDevFS_Driver gKB_DevInfo = { NULL, "PS2Keyboard", { .NumACLs = 0, - .Size = -1, - .Read = KB_Read, + .Size = 0, + //.Read = KB_Read, .IOCtl = KB_IOCtl } }; @@ -122,8 +122,8 @@ void KB_IRQHandler() if( !gbaKB_States[KEY_LSHIFT] && !gbaKB_States[KEY_RSHIFT] ) gbKB_ShiftState = 0; - KB_AddBuffer(KEY_KEYUP); - KB_AddBuffer(ch); + if(ch != 0 && gKB_Callback) + gKB_Callback( ch & 0x80000000 ); return; } @@ -140,7 +140,7 @@ void KB_IRQHandler() } // Ignore Non-Printable Characters - if(ch == 0 || ch & 0x80) return; + if(ch == 0) return; // --- Check for Kernel Magic Combos if(gbaKB_States[KEY_LCTRL] && gbaKB_States[KEY_LALT]) @@ -157,6 +157,7 @@ void KB_IRQHandler() { switch(ch) { + case 0: break; case '`': ch = '~'; break; case '1': ch = '!'; break; case '2': ch = '@'; break; @@ -185,48 +186,7 @@ void KB_IRQHandler() } } - if(gKB_Callback) gKB_Callback(ch); -} - -/** - * \fn void KB_AddBuffer(char ch) - * \brief Add to the keyboard ring buffer - */ -void KB_AddBuffer(char ch) -{ - // Add to buffer - gaKB_Buffer[ giKB_InsertPoint++ ] = ch; - // - Wrap - if( giKB_InsertPoint == KB_BUFFER_SIZE ) giKB_InsertPoint = 0; - // - Force increment read pointer - if( giKB_InsertPoint == giKB_ReadPoint ) giKB_ReadPoint ++; -} - -/** - * \fn Uint64 KB_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Dest) - * \brief Read from the ring buffer - * \param Node Unused - * \param Offset Unused (Character Device) - * \param Length Number of bytes to read - * \param Dest Destination - */ -Uint64 KB_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Dest) -{ - int pos = 0; - char *dstbuf = Dest; - - if(giKB_InUse) return -1; - giKB_InUse = 1; - - while(giKB_ReadPoint != giKB_InsertPoint && pos < Length) - { - dstbuf[pos++] = gaKB_Buffer[ giKB_ReadPoint++ ]; - if( giKB_ReadPoint == KB_BUFFER_SIZE ) giKB_InsertPoint = 0; - } - - giKB_InUse = 0; - - return Length; + if(gKB_Callback && ch != 0) gKB_Callback(ch); } /** diff --git a/Kernel/drv/kb_kbdus.h b/Kernel/drv/kb_kbdus.h index 94e515a2..4010bbeb 100644 --- a/Kernel/drv/kb_kbdus.h +++ b/Kernel/drv/kb_kbdus.h @@ -46,6 +46,7 @@ Uint8 gpKBDUS2[256] = { /*E0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*F0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +// - 0xE1 Prefixed Uint8 gpKBDUS3[256] = { // 0 1 2 3 4 5 6 7 8 9 A B C D E F /*00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0-F diff --git a/Kernel/drv/vterm.c b/Kernel/drv/vterm.c index 0f5cf8cf..f8a649af 100644 --- a/Kernel/drv/vterm.c +++ b/Kernel/drv/vterm.c @@ -6,40 +6,48 @@ #include #include #include +#include +#include // === CONSTANTS === +#define VERSION ((0<<8)|(50)) + #define NUM_VTS 4 -#define MAX_INPUT_CHARS 64 -#define VT_SCROLLBACK 1 // 4 Screens of text -#define DEFAULT_OUTPUT "/Devices/VGA" -#define DEFAULT_INPUT "/Devices/PS2Keyboard" +#define MAX_INPUT_CHARS32 64 +#define MAX_INPUT_CHARS8 (MAX_INPUT_CHARS32*4) +#define VT_SCROLLBACK 1 // 2 Screens of text +#define DEFAULT_OUTPUT "VGA" +//#define DEFAULT_OUTPUT "/Devices/BochsGA" +#define DEFAULT_INPUT "PS2Keyboard" #define DEFAULT_WIDTH 80 #define DEFAULT_HEIGHT 25 #define DEFAULT_COLOUR (VT_COL_BLACK|(0xAAA<<16)) #define VT_FLAG_HIDECSR 0x01 -enum eVT_Modes { - VT_MODE_TEXT8, // UTF-8 Text Mode (VT100 Emulation) - VT_MODE_TEXT32, // UTF-32 Text Mode (Acess Native) - VT_MODE_8BPP, // 256 Colour Mode - VT_MODE_16BPP, // 16 bit Colour Mode - VT_MODE_24BPP, // 24 bit Colour Mode - VT_MODE_32BPP, // 32 bit Colour Mode - NUM_VT_MODES +enum eVT_InModes { + VT_INMODE_TEXT8, // UTF-8 Text Mode (VT100 Emulation) + VT_INMODE_TEXT32, // UTF-32 Text Mode (Acess Native) + NUM_VT_INMODES }; // === TYPES === typedef struct { - int Mode; - int Flags; - int Width, Height; - int ViewPos, WritePos; - Uint32 CurColour; - char Name[2]; - int InputRead; - int InputWrite; - Uint32 InputBuffer[MAX_INPUT_CHARS]; + int Mode; //!< Current Mode (see ::eTplTerminal_Modes) + int Flags; //!< Flags (see VT_FLAG_*) + short Width; //!< Virtual Width + short Height; //!< Virtual Height + short RealWidth; //!< Real Width + short RealHeight; //!< Real Height + + int ViewPos; //!< View Buffer Offset (Text Only) + int WritePos; //!< Write Buffer Offset (Text Only) + Uint32 CurColour; //!< Current Text Colour + char Name[2]; //!< Name of the terminal + + int InputRead; //!< Input buffer read position + int InputWrite; //!< Input buffer write position + char InputBuffer[MAX_INPUT_CHARS8]; union { tVT_Char *Text; Uint32 *Buffer; @@ -51,9 +59,11 @@ typedef struct { int VT_Install(char **Arguments); char *VT_ReadDir(tVFS_Node *Node, int Pos); tVFS_Node *VT_FindDir(tVFS_Node *Node, char *Name); + int VT_Root_IOCtl(tVFS_Node *Node, int Id, void *Data); Uint64 VT_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer); Uint64 VT_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer); - int VT_IOCtl(tVFS_Node *Node, int Id, void *Data); + int VT_Terminal_IOCtl(tVFS_Node *Node, int Id, void *Data); +void VT_SetTerminal(int ID); void VT_KBCallBack(Uint32 Codepoint); void VT_int_PutString(tVTerm *Term, Uint8 *Buffer, Uint Count); int VT_int_ParseEscape(tVTerm *Term, char *Buffer); @@ -67,7 +77,7 @@ const Uint16 caVT100Colours[] = { }; // === GLOBALS === -MODULE_DEFINE(0, 0x0032, VTerm, VT_Install, NULL, NULL); +MODULE_DEFINE(0, VERSION, VTerm, VT_Install, NULL, DEFAULT_OUTPUT, DEFAULT_INPUT, NULL); tDevFS_Driver gVT_DrvInfo = { NULL, "VTerm", { @@ -76,15 +86,22 @@ tDevFS_Driver gVT_DrvInfo = { .Inode = -1, .NumACLs = 0, .ReadDir = VT_ReadDir, - .FindDir = VT_FindDir + .FindDir = VT_FindDir, + .IOCtl = VT_Root_IOCtl } }; +// --- Terminals --- tVTerm gVT_Terminals[NUM_VTS]; + int giVT_CurrentTerminal = 0; +// --- Driver Handles --- char *gsVT_OutputDevice = NULL; char *gsVT_InputDevice = NULL; int giVT_OutputDevHandle = -2; int giVT_InputDevHandle = -2; - int giVT_CurrentTerminal = 0; +// --- Key States --- (Used for VT Switching/Magic Combos) + int gbVT_CtrlDown = 0; + int gbVT_AltDown = 0; + int gbVT_SysrqDown = 0; // === CODE === /** @@ -129,8 +146,8 @@ int VT_Install(char **Arguments) } // Apply Defaults - if(!gsVT_OutputDevice) gsVT_OutputDevice = DEFAULT_OUTPUT; - if(!gsVT_InputDevice) gsVT_InputDevice = DEFAULT_INPUT; + if(!gsVT_OutputDevice) gsVT_OutputDevice = "/Devices/"DEFAULT_OUTPUT; + if(!gsVT_InputDevice) gsVT_InputDevice = "/Devices/"DEFAULT_INPUT; LOG("Using '%s' as output", gsVT_OutputDevice); LOG("Using '%s' as input", gsVT_InputDevice); @@ -138,7 +155,7 @@ int VT_Install(char **Arguments) // Create Nodes for( i = 0; i < NUM_VTS; i++ ) { - gVT_Terminals[i].Mode = VT_MODE_TEXT8; + gVT_Terminals[i].Mode = TERM_MODE_TEXT; gVT_Terminals[i].Flags = 0; gVT_Terminals[i].Width = DEFAULT_WIDTH; gVT_Terminals[i].Height = DEFAULT_HEIGHT; @@ -152,11 +169,12 @@ int VT_Install(char **Arguments) gVT_Terminals[i].Name[0] = '0'+i; gVT_Terminals[i].Name[1] = '\0'; gVT_Terminals[i].Node.Inode = i; + gVT_Terminals[i].Node.ImplPtr = &gVT_Terminals[i]; gVT_Terminals[i].Node.NumACLs = 0; // Only root can open virtual terminals gVT_Terminals[i].Node.Read = VT_Read; gVT_Terminals[i].Node.Write = VT_Write; - gVT_Terminals[i].Node.IOCtl = VT_IOCtl; + gVT_Terminals[i].Node.IOCtl = VT_Terminal_IOCtl; } // Add to DevFS @@ -173,6 +191,7 @@ void VT_InitOutput() { giVT_OutputDevHandle = VFS_Open(gsVT_OutputDevice, VFS_OPENFLAG_WRITE); LOG("giVT_OutputDevHandle = %x\n", giVT_OutputDevHandle); + VT_SetTerminal( 0 ); } /** @@ -228,6 +247,44 @@ tVFS_Node *VT_FindDir(tVFS_Node *Node, char *Name) return &gVT_Terminals[num].Node; } +/** + * \fn int VT_Root_IOCtl(tVFS_Node *Node, int Id, void *Data) + * \brief Control the VTerm Driver + */ +int VT_Root_IOCtl(tVFS_Node *Node, int Id, void *Data) +{ + int len; + switch(Id) + { + case DRV_IOCTL_TYPE: return DRV_TYPE_MISC; + case DRV_IOCTL_IDENT: memcpy(Data, "VT\0\0", 4); return 0; + case DRV_IOCTL_VERSION: return VERSION; + case DRV_IOCTL_LOOKUP: return 0; + + case 4: // Get Video Driver + if(Data) strcpy(Data, gsVT_OutputDevice); + return strlen(gsVT_OutputDevice); + + case 5: // Set Video Driver + if(!Data) return -EINVAL; + if(Threads_GetUID() != 0) return -EACCES; + + len = strlen(Data); + + free(gsVT_OutputDevice); + + gsVT_OutputDevice = malloc(len+1); + strcpy(gsVT_OutputDevice, Data); + + VFS_Close(giVT_OutputDevHandle); + giVT_OutputDevHandle = -1; + + VT_InitOutput(); + return 1; + } + return 0; +} + /** * \fn Uint64 VT_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) * \brief Read from a virtual terminal @@ -240,29 +297,29 @@ Uint64 VT_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) // Check current mode switch(term->Mode) { - case VT_MODE_TEXT8: + case TERM_MODE_TEXT: while(pos < Length) { while(term->InputRead == term->InputWrite) Threads_Yield(); - while(term->InputRead != term->InputWrite) - { - pos += WriteUTF8(Buffer+pos, term->InputBuffer[term->InputRead]); - term->InputRead ++; - term->InputRead %= MAX_INPUT_CHARS; - } + + ((char*)Buffer)[pos] = term->InputBuffer[term->InputRead]; + pos ++; + term->InputRead ++; + term->InputRead %= MAX_INPUT_CHARS8; } break; - case VT_MODE_TEXT32: + case TERM_MODE_FB: + case TERM_MODE_OPENGL: while(pos < Length) { while(term->InputRead == term->InputWrite) Threads_Yield(); while(term->InputRead != term->InputWrite) { - ((Uint32*)Buffer)[pos] = term->InputBuffer[term->InputRead]; + ((Uint32*)Buffer)[pos] = ((Uint32*)term->InputBuffer)[term->InputRead]; pos ++; term->InputRead ++; - term->InputRead %= MAX_INPUT_CHARS; + term->InputRead %= MAX_INPUT_CHARS32; } } break; @@ -283,12 +340,9 @@ Uint64 VT_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) // Write switch( term->Mode ) { - case VT_MODE_TEXT8: + case TERM_MODE_TEXT: VT_int_PutString(term, Buffer, Length); break; - case VT_MODE_TEXT32: - //VT_int_PutString32(term, Buffer, Length); - break; } //LEAVE('i', 0); @@ -296,14 +350,78 @@ Uint64 VT_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) } /** - * \fn int VT_IOCtl(tVFS_Node *Node, int Id, void *Data) + * \fn int VT_Terminal_IOCtl(tVFS_Node *Node, int Id, void *Data) * \brief Call an IO Control on a virtual terminal */ -int VT_IOCtl(tVFS_Node *Node, int Id, void *Data) +int VT_Terminal_IOCtl(tVFS_Node *Node, int Id, void *Data) { + int *iData = Data; + tVTerm *term = Node->ImplPtr; + switch(Id) + { + case DRV_IOCTL_TYPE: return DRV_TYPE_TERMINAL; + case DRV_IOCTL_IDENT: memcpy(Data, "VT\0\0", 4); return 0; + case DRV_IOCTL_VERSION: return VERSION; + case DRV_IOCTL_LOOKUP: return 0; + + // Get/Set the mode (and apply any changes) + case TERM_IOCTL_MODETYPE: + if(Data == NULL) return term->Mode; + term->Mode = *iData; + // Update the screen dimensions + if(giVT_CurrentTerminal == Node->Inode) + VT_SetTerminal( giVT_CurrentTerminal ); + break; + + // Get/set the terminal width + case TERM_IOCTL_WIDTH: + if(Data == NULL) return term->Width; + term->Width = *iData; + break; + + // Get/set the terminal height + case TERM_IOCTL_HEIGHT: + if(Data == NULL) return term->Height; + term->Height = *iData; + break; + + default: + return -1; + } return 0; } +/** + * \fn void VT_SetTerminal(int ID) + * \brief Set the current terminal + */ +void VT_SetTerminal(int ID) +{ + tVideo_IOCtl_Mode mode = {0}; + int modeNum; + + // Create the video mode + mode.width = gVT_Terminals[ ID ].Width; + mode.height = gVT_Terminals[ ID ].Height; + // - Text Mode + if(gVT_Terminals[ ID ].Mode == TERM_MODE_TEXT) { + mode.bpp = 12; + mode.flags = VIDEO_FLAG_TEXT; + } + // - Framebuffer or 3D + else { + mode.bpp = 32; + mode.flags = 0; + } + + // Set video mode + VFS_IOCtl( giVT_OutputDevHandle, VIDEO_IOCTL_FINDMODE, &mode ); + modeNum = mode.id; + gVT_Terminals[ ID ].RealWidth = mode.width; + gVT_Terminals[ ID ].RealHeight = mode.height; + VFS_IOCtl( giVT_OutputDevHandle, VIDEO_IOCTL_SETMODE, &modeNum ); +} + /** * \fn void VT_KBCallBack(Uint32 Codepoint) * \brief Called on keyboard interrupt @@ -312,12 +430,113 @@ void VT_KBCallBack(Uint32 Codepoint) { tVTerm *term = &gVT_Terminals[giVT_CurrentTerminal]; - term->InputBuffer[ term->InputWrite ] = Codepoint; - term->InputWrite ++; - term->InputWrite %= MAX_INPUT_CHARS; - if(term->InputRead == term->InputWrite) { - term->InputRead ++; - term->InputRead %= MAX_INPUT_CHARS; + // How the hell did we get a Codepoint of zero? + if(Codepoint == 0) return; + + // Key Up + if( Codepoint & 0x80000000 ) + { + Codepoint &= 0x7FFFFFFF; + switch(Codepoint) + { + case KEY_LALT: + case KEY_RALT: + gbVT_AltDown = 0; + break; + case KEY_LCTRL: + case KEY_RCTRL: + gbVT_CtrlDown = 0; + break; + } + return; + } + + switch(Codepoint) + { + case KEY_LALT: + case KEY_RALT: + gbVT_AltDown = 1; + break; + case KEY_LCTRL: + case KEY_RCTRL: + gbVT_CtrlDown = 1; + break; + + default: + if(!gbVT_AltDown || !gbVT_CtrlDown) + break; + switch(Codepoint) + { + case KEY_F1: + giVT_CurrentTerminal = 0; + break; + case KEY_F2: + giVT_CurrentTerminal = 0; + break; + case KEY_F3: + giVT_CurrentTerminal = 0; + break; + case KEY_F4: + giVT_CurrentTerminal = 0; + break; + } + return; + } + + // Encode key + if(term->Mode == TERM_MODE_TEXT) + { + Uint8 buf[6] = {0}; + int len; + + // Ignore Modifer Keys + if(Codepoint > KEY_MODIFIERS) return; + + // Get UTF-8/ANSI Encoding + switch(Codepoint) + { + case KEY_LEFT: + buf[0] = '\x1B'; buf[1] = '['; + buf[2] = 'D'; len = 3; + break; + case KEY_RIGHT: + buf[0] = '\x1B'; buf[1] = '['; + buf[2] = 'C'; len = 3; + break; + default: + len = WriteUTF8( buf, Codepoint ); + //Log("Codepoint = 0x%x", Codepoint); + break; + } + + //Log("len = %i, buf = %s", len, buf); + + // Write + if( MAX_INPUT_CHARS8 - term->InputWrite >= len ) + memcpy( &term->InputBuffer[term->InputWrite], buf, len ); + else { + memcpy( &term->InputBuffer[term->InputWrite], buf, MAX_INPUT_CHARS8 - term->InputWrite ); + memcpy( &term->InputBuffer[0], buf, len - (MAX_INPUT_CHARS8 - term->InputWrite) ); + } + // Roll the buffer over + term->InputWrite += len; + term->InputWrite %= MAX_INPUT_CHARS8; + if( (term->InputWrite - term->InputRead + MAX_INPUT_CHARS8)%MAX_INPUT_CHARS8 < len ) { + term->InputRead = term->InputWrite + 1; + term->InputRead %= MAX_INPUT_CHARS8; + } + + } + else + { + // Encode the raw UTF-32 Key + ((Uint32*)term->InputBuffer)[ term->InputWrite ] = Codepoint; + term->InputWrite ++; + term->InputWrite %= MAX_INPUT_CHARS32; + if(term->InputRead == term->InputWrite) { + term->InputRead ++; + term->InputRead %= MAX_INPUT_CHARS32; + } } } @@ -380,6 +599,7 @@ int VT_int_ParseEscape(tVTerm *Term, char *Buffer) { char c; int argc = 0, j = 1; + int tmp; int args[4] = {0,0,0,0}; switch(Buffer[0]) { @@ -393,7 +613,7 @@ int VT_int_ParseEscape(tVTerm *Term, char *Buffer) args[argc] += c-'0'; c = Buffer[++j]; } - argc ++; + if( j != 1 ) argc ++; } while(c == ';'); // Get string (what does this do?) @@ -406,8 +626,32 @@ int VT_int_ParseEscape(tVTerm *Term, char *Buffer) // Get Command if( ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')) { - switch(c) { - //Clear By Line + switch(c) + { + // Left + case 'D': + if(argc == 1) tmp = args[0]; + else tmp = 1; + + if( Term->WritePos-(tmp-1) % Term->Width == 0 ) + Term->WritePos -= Term->WritePos % Term->Width; + else + Term->WritePos -= tmp; + Log("Left by %i", tmp); + break; + + // Right + case 'C': + if(argc == 1) tmp = args[0]; + else tmp = 1; + if( (Term->WritePos + tmp) % Term->Width == 0 ) { + Term->WritePos -= Term->WritePos % Term->Width; + Term->WritePos += Term->Width - 1; + } else + Term->WritePos += tmp; + break; + + // Clear By Line case 'J': // Clear Screen switch(args[0]) diff --git a/Kernel/include/modules.h b/Kernel/include/modules.h index bf3171b3..68c797be 100644 --- a/Kernel/include/modules.h +++ b/Kernel/include/modules.h @@ -17,9 +17,9 @@ # error "Unknown architecture when determining MODULE_ARCH_ID ('" #ARCH "')" #endif -#define MODULE_DEFINE(_flags,_ver,_ident,_entry,_deps...) char *_DriverDeps_##_ident[]={_deps};\ +#define MODULE_DEFINE(_flags,_ver,_ident,_entry,_deinit,_deps...) char *_DriverDeps_##_ident[]={_deps};\ tModule __attribute__ ((section ("KMODULES"),unused)) _DriverInfo_##_ident=\ - {MODULE_MAGIC,MODULE_ARCH_ID,_flags,_ver,NULL,#_ident,_entry,_DriverDeps_##_ident} + {MODULE_MAGIC,MODULE_ARCH_ID,_flags,_ver,NULL,#_ident,_entry,_deinit,_DriverDeps_##_ident} typedef struct sModule { Uint32 Magic; @@ -29,6 +29,7 @@ typedef struct sModule { struct sModule *Next; char *Name; int (*Init)(char **Arguments); + void (*Deinit)(); char **Dependencies; // NULL Terminated List } __attribute__((packed)) tModule; diff --git a/Kernel/include/syscalls.h b/Kernel/include/syscalls.h index a615c37d..2c44d2c8 100644 --- a/Kernel/include/syscalls.h +++ b/Kernel/include/syscalls.h @@ -26,6 +26,7 @@ enum eSyscalls { SYS_EXECVE, // 17 - Replace the current process SYS_LOADBIN, // 18 - Load a binary into the current address space SYS_UNLOADBIN, // 19 - Unload a loaded binary + SYS_LOADMOD, // 20 - Load a module into the kernel SYS_GETPHYS = 32, // 32 - Get the physical address of a page SYS_MAP, // 33 - Map a physical address @@ -64,7 +65,7 @@ static const char *cSYSCALL_NAMES[] = { "SYS_EXIT","SYS_CLONE","SYS_KILL","SYS_SIGNAL","SYS_YIELD","SYS_SLEEP", "SYS_WAIT","SYS_WAITTID","SYS_SETNAME","SYS_GETNAME","SYS_GETTID","SYS_GETPID", "SYS_SETPRI","SYS_SENDMSG","SYS_GETMSG","SYS_GETTIME","SYS_SPAWN","SYS_EXECVE", - "SYS_LOADBIN","SYS_UNLOADBIN","","","","", + "SYS_LOADBIN","SYS_UNLOADBIN","SYS_LOADMOD","","","", "","","","","","", "","","SYS_GETPHYS","SYS_MAP","SYS_ALLOCATE","SYS_UNMAP", "SYS_PREALLOC","SYS_SETFLAGS","SYS_SHAREWITH","SYS_GETUID","SYS_GETGID","SYS_SETUID", diff --git a/Kernel/include/syscalls.inc.asm b/Kernel/include/syscalls.inc.asm index 9f3973af..178ecbd6 100644 --- a/Kernel/include/syscalls.inc.asm +++ b/Kernel/include/syscalls.inc.asm @@ -22,6 +22,7 @@ %define SYS_EXECVE 17 ; Replace the current process %define SYS_LOADBIN 18 ; Load a binary into the current address space %define SYS_UNLOADBIN 19 ; Unload a loaded binary +%define SYS_LOADMOD 20 ; Load a module into the kernel %define SYS_GETPHYS 32 ; Get the physical address of a page %define SYS_MAP 33 ; Map a physical address diff --git a/Kernel/include/tpl_drv_keyboard.h b/Kernel/include/tpl_drv_keyboard.h index 9d3e5dca..77f8295a 100644 --- a/Kernel/include/tpl_drv_keyboard.h +++ b/Kernel/include/tpl_drv_keyboard.h @@ -27,9 +27,7 @@ enum { KEY_ESC = 0x1B, KEY_NP_MASK = 0x80, //End of ASCII Range - KEY_LCTRL, KEY_RCTRL, - KEY_LALT, KEY_RALT, - KEY_LSHIFT, KEY_RSHIFT, + KEY_CAPSLOCK, KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT, KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, @@ -43,6 +41,12 @@ enum { KEY_KPEND, KEY_KPDOWN, KEY_KPPGDN, KEY_KPINS, KEY_KPDEL, KEY_WIN, KEY_MENU, + // Modifiers + KEY_MODIFIERS = 0xC0, + KEY_LCTRL, KEY_RCTRL, + KEY_LALT, KEY_RALT, + KEY_LSHIFT, KEY_RSHIFT, + KEY_KEYUP = 0xFF }; diff --git a/Kernel/include/tpl_drv_video.h b/Kernel/include/tpl_drv_video.h index 51f6ea94..b84a97e2 100644 --- a/Kernel/include/tpl_drv_video.h +++ b/Kernel/include/tpl_drv_video.h @@ -54,16 +54,21 @@ struct sVideo_IOCtl_Mode { Uint8 bpp; //!< Bits per Pixel Uint8 flags; //!< Mode Flags }; -#define VIDEO_FLAG_TEXT 0x1 //!< Text Mode +typedef struct sVideo_IOCtl_Mode tVideo_IOCtl_Mode; //!< Mode Type +/** + * \brief Text Mode Flag + * \note A text mode should have the ::sVideo_IOCtl_Mode.bpp set to 12 + */ +#define VIDEO_FLAG_TEXT 0x1 #define VIDEO_FLAG_SLOW 0x2 //!< Non-accelerated mode + +typedef struct sVideo_IOCtl_Pos tVideo_IOCtl_Pos; //!< Position Type /** */ struct sVideo_IOCtl_Pos { - Sint16 x; - Sint16 y; + Sint16 x; //!< X Coordinate + Sint16 y; //!< Y Coordinate }; -typedef struct sVideo_IOCtl_Mode tVideo_IOCtl_Mode; //!< Mode Type -typedef struct sVideo_IOCtl_Pos tVideo_IOCtl_Pos; //!< Mode Type /** * \struct sVT_Char diff --git a/Kernel/lib.c b/Kernel/lib.c index d3fff546..5bed4ca2 100644 --- a/Kernel/lib.c +++ b/Kernel/lib.c @@ -171,7 +171,7 @@ int DivUp(int num, int dem) } /** - * \fn int strpos8(char *str, Uint32 search) + * \fn int strpos8(const char *str, Uint32 search) * \brief Search a string for a UTF-8 character */ int strpos8(const char *str, Uint32 Search) diff --git a/Kernel/messages.c b/Kernel/messages.c index 93cf6ca4..057f9979 100644 --- a/Kernel/messages.c +++ b/Kernel/messages.c @@ -12,6 +12,8 @@ * \brief Send an IPC message * \param Err Pointer to the errno variable * \param Dest Destination Thread + * \param Length Length of the message + * \param Data Message data */ int Proc_SendMessage(Uint *Err, Uint Dest, int Length, void *Data) { @@ -63,6 +65,9 @@ int Proc_SendMessage(Uint *Err, Uint Dest, int Length, void *Data) /** * \fn int Proc_GetMessage(Uint *Err, Uint *Source, void *Buffer) * \brief Gets a message + * \param Err Pointer to \a errno + * \param Source Where to put the source TID + * \param Buffer Buffer to place the message data (set to NULL to just get message length) */ int Proc_GetMessage(Uint *Err, Uint *Source, void *Buffer) { diff --git a/Kernel/proc.c b/Kernel/proc.c deleted file mode 100644 index e5d9f8f1..00000000 --- a/Kernel/proc.c +++ /dev/null @@ -1,653 +0,0 @@ -/* - * AcessOS Microkernel Version - * proc.c - */ -#include -#include -#include -#include -#include - -// === CONSTANTS === -#define RANDOM_SEED 0xACE55051 -#define SWITCH_MAGIC 0xFFFACE55 // There is no code in this area -#define DEFAULT_QUANTUM 10 -#define DEFAULT_TICKETS 5 -#define MAX_TICKETS 10 -#define TIMER_DIVISOR 11931 //~100Hz - -// === MACROS === -#define TIMER_BASE 1193182 //Hz -#define MS_PER_TICK_WHOLE (1000*(TIMER_DIVISOR)/(TIMER_BASE)) -#define MS_PER_TICK_FRACT ((Uint64)(1000*TIMER_DIVISOR-((Uint64)MS_PER_TICK_WHOLE)*TIMER_BASE)*(0x80000000/TIMER_BASE)) - -// === IMPORTS === -extern Uint GetEIP(); // start.asm -extern Uint32 gaInitPageDir[1024]; // start.asm -extern void Kernel_Stack_Top; - -// === PROTOTYPES === -void Proc_Start(); -static tThread *Proc_int_GetPrevThread(tThread **List, tThread *Thread); -void Proc_Scheduler(); -Uint rand(); - -// === GLOBALS === -// -- Core Thread -- -tThread gThreadZero = { - NULL, 0, // Next, Lock - THREAD_STAT_ACTIVE, // Status - 0, 0, // TID, TGID - 0, 0, // UID, GID - "ThreadZero", // Name - 0, 0, 0, // ESP, EBP, EIP (Set on switch) - (Uint)&gaInitPageDir-KERNEL_BASE, // CR3 - (Uint)&Kernel_Stack_Top, // Kernel Stack (Unused as it it PL0) - NULL, NULL, // Messages, Last Message - DEFAULT_QUANTUM, DEFAULT_QUANTUM, // Quantum, Remaining - DEFAULT_TICKETS - }; -// -- Processes -- -// --- Locks --- - int giThreadListLock = 0; ///\note NEVER use a heap function while locked -// --- Current State --- -tThread *gCurrentThread = NULL; - int giNumActiveThreads = 0; - int giTotalTickets = 0; -Uint giNextTID = 1; -// --- Thread Lists --- -tThread *gActiveThreads = NULL; // Currently Running Threads -tThread *gSleepingThreads = NULL; // Sleeping Threads -tThread *gDeleteThreads = NULL; // Threads to delete -// --- Timekeeping --- -Uint64 giTicks = 0; -Uint64 giTimestamp = 0; -Uint64 giPartMiliseconds = 0; -// --- Multiprocessing --- - int giNumCPUs = 1; -tMPInfo *gMPTable = NULL; -tTSS *gTSSs = NULL; -tTSS gTSS0 = {0}; - -// === CODE === -/** - * \fn void Proc_Start() - * \brief Starts the process scheduler - */ -void Proc_Start() -{ - Uint pos; - // -- Initialise Multiprocessing - // Find MP Floating Table - // - EBDA - for(pos = KERNEL_BASE|0x9FC00; pos < (KERNEL_BASE|0xA0000); pos += 16) { - if( *(Uint*)(pos) == MPTABLE_IDENT ) { - if(ByteSum( (void*)pos, sizeof(tMPInfo) ) != 0) continue; - gMPTable = (void*)pos; - break; - } - } - // - Last KiB - if(!gMPTable) { - - } - // - BIOS ROM - if(!gMPTable) { - for(pos = KERNEL_BASE|0xF0000; pos < (KERNEL_BASE|0x100000); pos += 16) { - if( *(Uint*)(pos) == MPTABLE_IDENT ) { - if(ByteSum( (void*)pos, sizeof(tMPInfo) ) != 0) continue; - gMPTable = (void*)pos; - break; - } - } - } - - // If the MP Table Exists, parse it - if(gMPTable) - { - Panic("Uh oh... MP Table Parsing is unimplemented\n"); - } else { - giNumCPUs = 1; - gTSSs = &gTSS0; - } - - // Initialise TSS - for(pos=0;pos> 16; - gGDT[9+pos].BaseHi = (Uint)&gTSSs[pos] >> 24; - } - for(pos=0;pos>8)&0xFF); // High Byte - - // Clear timestamp - giTimestamp = 0; - giPartMiliseconds = 0; - giTicks = 0; - - // Create Initial Task - gActiveThreads = &gThreadZero; - gCurrentThread = &gThreadZero; - giTotalTickets = gThreadZero.NumTickets; - giNumActiveThreads = 1; - - // Create Idle Task - if(Proc_Clone(0, 0) == 0) - { - gCurrentThread->ThreadName = "Idle Thread"; - Proc_SetTickets(0); // Never called randomly - gCurrentThread->Quantum = 1; // 1 slice quantum - for(;;) __asm__ __volatile__ ("hlt"); // Just yeilds - } - - // Start Interrupts (and hence scheduler) - __asm__ __volatile__("sti"); -} - -/** - * \fn int Proc_Clone(Uint *Err, Uint Flags) - * \brief Clone the current process - */ -int Proc_Clone(Uint *Err, Uint Flags) -{ - tThread *newThread; - Uint eip, esp, ebp; - - __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 old - memcpy(newThread, gCurrentThread, sizeof(tThread)); - // Initialise Memory Space (New Addr space or kernel stack) - if(Flags & CLONE_VM) { - newThread->TGID = newThread->TID; - newThread->CR3 = MM_Clone(); - } else { - Uint tmpEbp, oldEsp = esp; - - // Create new KStack - newThread->KernelStack = MM_NewKStack(); - // Check for errors - if(newThread->KernelStack == 0) { - free(newThread); - return -1; - } - - // Get ESP as a used size - esp = gCurrentThread->KernelStack - esp; - // Copy used stack - memcpy( (void*)(newThread->KernelStack - esp), (void*)(gCurrentThread->KernelStack - esp), esp ); - // Get ESP as an offset in the new stack - esp = newThread->KernelStack - esp; - // Adjust EBP - ebp = newThread->KernelStack - (gCurrentThread->KernelStack - ebp); - - // Repair EBPs & Stack Addresses - #if 0 - tmpEbp = ebp; - while(oldEsp < *(Uint*)tmpEbp && *(Uint*)tmpEbp < gCurrentThread->KernelStack) - { - *(Uint*)tmpEbp += newThread->KernelStack - gCurrentThread->KernelStack; - tmpEbp = *(Uint*)tmpEbp; - } - #else // Catches arguments also, but may trash stack-address-like values - for(tmpEbp = esp; tmpEbp < newThread->KernelStack; tmpEbp += 4) - { - if(oldEsp < *(Uint*)tmpEbp && *(Uint*)tmpEbp < gCurrentThread->KernelStack) - *(Uint*)tmpEbp += newThread->KernelStack - gCurrentThread->KernelStack; - } - #endif - } - - // Set Pointer, Spinlock and TID - newThread->Next = NULL; - newThread->IsLocked = 0; - newThread->TID = giNextTID++; - - // 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->ESP = esp; - newThread->EBP = ebp; - eip = GetEIP(); - if(eip == SWITCH_MAGIC) { - outb(0x20, 0x20); // ACK Timer and return as child - return 0; - } - - // Set EIP as parent - newThread->EIP = eip; - - //Log(" Proc_Clone: giTimestamp = %i.%07i", (Uint)giTimestamp, (Uint)giPartMiliseconds/214); - - // Lock list and add to active - LOCK( &giThreadListLock ); - newThread->Next = gActiveThreads; - gActiveThreads = newThread; - giNumActiveThreads ++; - giTotalTickets += newThread->NumTickets; - RELEASE( &giThreadListLock ); - - return newThread->TID; -} - -/** - * \fn void Proc_Exit() - * \brief Kill the current process - */ -void Proc_Exit() -{ - tThread *thread; - tMsg *msg; - - ///\note Double lock is needed due to overlap of locks - - // Lock thread (stop us recieving messages) - LOCK( &gCurrentThread->IsLocked ); - - // Lock thread list - LOCK( &giThreadListLock ); - - // Get previous thread on list - thread = Proc_int_GetPrevThread( &gActiveThreads, gCurrentThread ); - if(!thread) { - Warning("Proc_Exit - Current thread is not on the active queue"); - return; - } - - // Clear Message Queue - while( gCurrentThread->Messages ) - { - msg = gCurrentThread->Messages->Next; - free( gCurrentThread->Messages ); - gCurrentThread->Messages = msg; - } - - gCurrentThread->Remaining = 0; // Clear Remaining Quantum - gCurrentThread->Quantum = 0; // Clear Quantum to indicate dead thread - thread->Next = gCurrentThread->Next; // Remove from active - - // Add to delete queue - if(gDeleteThreads) { - gCurrentThread->Next = gDeleteThreads; - gDeleteThreads = gCurrentThread; - } else { - gCurrentThread->Next = NULL; - gDeleteThreads = gCurrentThread; - } - - giNumActiveThreads --; - giTotalTickets -= gCurrentThread->NumTickets; - - // Mark thread as sleeping - gCurrentThread->Status = THREAD_STAT_DEAD; - - // Release spinlocks - RELEASE( &gCurrentThread->IsLocked ); // Released first so that it IS released - RELEASE( &giThreadListLock ); - __asm__ __volatile__ ("hlt"); -} - -/** - * \fn void Proc_Yield() - * \brief Yield remainder of timeslice - */ -void Proc_Yield() -{ - gCurrentThread->Quantum = 0; - __asm__ __volatile__ ("hlt"); -} - -/** - * \fn void Proc_Sleep() - * \brief Take the current process off the run queue - */ -void Proc_Sleep() -{ - tThread *thread; - - //Log("Proc_Sleep: %i going to sleep", gCurrentThread->TID); - - // Acquire Spinlock - LOCK( &giThreadListLock ); - - // Get thread before current thread - thread = Proc_int_GetPrevThread( &gActiveThreads, gCurrentThread ); - if(!thread) { - Warning("Proc_Sleep - Current thread is not on the active queue"); - return; - } - - // Don't sleep if there is a message waiting - if( gCurrentThread->Messages ) { - RELEASE( &giThreadListLock ); - return; - } - - // Unset remaining timeslices (force a task switch on timer fire) - gCurrentThread->Remaining = 0; - - // Remove from active list - thread->Next = gCurrentThread->Next; - - // Add to Sleeping List (at the top) - gCurrentThread->Next = gSleepingThreads; - gSleepingThreads = gCurrentThread; - - // Reduce the active count & ticket count - giNumActiveThreads --; - giTotalTickets -= gCurrentThread->NumTickets; - - // Mark thread as sleeping - gCurrentThread->Status = THREAD_STAT_SLEEPING; - - // Release Spinlock - RELEASE( &giThreadListLock ); - - __asm__ __volatile__ ("hlt"); -} - -/** - * \fn void Thread_Wake( tThread *Thread ) - * \brief Wakes a sleeping/waiting thread up - */ -void Thread_Wake(tThread *Thread) -{ - tThread *prev; - switch(Thread->Status) - { - case THREAD_STAT_ACTIVE: break; - case THREAD_STAT_SLEEPING: - LOCK( &giThreadListLock ); - prev = Proc_int_GetPrevThread(&gSleepingThreads, Thread); - prev->Next = Thread->Next; // Remove from sleeping queue - Thread->Next = gActiveThreads; // Add to active queue - gActiveThreads = Thread; - Thread->Status = THREAD_STAT_ACTIVE; - RELEASE( &giThreadListLock ); - break; - case THREAD_STAT_WAITING: - Warning("Thread_Wake - Waiting threads are not currently supported"); - break; - case THREAD_STAT_DEAD: - Warning("Thread_Wake - Attempt to wake dead thread (%i)", Thread->TID); - break; - default: - Warning("Thread_Wake - Unknown process status (%i)\n", Thread->Status); - break; - } -} - -/** - * \fn int Proc_Demote(Uint *Err, int Dest, tRegs *Regs) - * \brief Demotes a process to a lower permission level - * \param Err Pointer to user's errno - */ -int Proc_Demote(Uint *Err, int Dest, tRegs *Regs) -{ - int cpl = Regs->cs & 3; - // Sanity Check - if(Dest > 3 || Dest < 0) { - *Err = -EINVAL; - return -1; - } - - // Permission Check - if(cpl > Dest) { - *Err = -EACCES; - return -1; - } - - // Change the Segment Registers - Regs->cs = (((Dest+1)<<4) | Dest) - 8; - Regs->ss = ((Dest+1)<<4) | Dest; - // Check if the GP Segs are GDT, then change them - if(!(Regs->ds & 4)) Regs->ds = ((Dest+1)<<4) | Dest; - if(!(Regs->es & 4)) Regs->es = ((Dest+1)<<4) | Dest; - if(!(Regs->fs & 4)) Regs->fs = ((Dest+1)<<4) | Dest; - if(!(Regs->gs & 4)) Regs->gs = ((Dest+1)<<4) | Dest; - - return 0; -} - -/** - * \fn void Proc_SetTickets(int Num) - * \brief Sets the 'priority' of a task - */ -void Proc_SetTickets(int Num) -{ - if(Num < 0) return; - if(Num > MAX_TICKETS) Num = MAX_TICKETS; - - Log("Proc_SetTickets: (Num=%i)", Num); - Log(" Proc_SetTickets: giTotalTickets = %i", giTotalTickets); - LOCK( &giThreadListLock ); - giTotalTickets -= gCurrentThread->NumTickets; - gCurrentThread->NumTickets = Num; - giTotalTickets += Num; - RELEASE( &giThreadListLock ); - Log(" Proc_SetTickets: giTotalTickets = %i", giTotalTickets); - Log("Proc_SetTickets: RETURN", giTotalTickets); -} - -/** - * \fn tThread *Proc_GetThread(Uint TID) - * \brief Gets a thread given its TID - */ -tThread *Proc_GetThread(Uint TID) -{ - tThread *thread; - - // Search Active List - for(thread = gActiveThreads; - thread; - thread = thread->Next) - { - if(thread->TID == TID) - return thread; - } - - // Search Sleeping List - for(thread = gSleepingThreads; - thread; - thread = thread->Next) - { - if(thread->TID == TID) - return thread; - } - - return NULL; -} - -/** - * \fn static tThread *Proc_int_GetPrevThread(tThread *List, tThread *Thread) - * \brief Gets the previous entry in a thead linked list - */ -static tThread *Proc_int_GetPrevThread(tThread **List, tThread *Thread) -{ - tThread *ret; - // First Entry - if(*List == Thread) { - return (tThread*)List; - } else { - for(ret = *List; - ret->Next && ret->Next != Thread; - ret = ret->Next - ); - // Error if the thread is not on the list - if(!ret->Next || ret->Next != Thread) { - return NULL; - } - } - return ret; -} - -/** - * \fn void Proc_DumpThreads() - */ -void Proc_DumpThreads() -{ - tThread *thread; - - Log("Active Threads:"); - for(thread=gActiveThreads;thread;thread=thread->Next) - { - Log(" %i (%i) - %s", thread->TID, thread->TGID, thread->ThreadName); - Log(" %i Tickets, Quantum %i", thread->NumTickets, thread->Quantum); - Log(" CR3 0x%x, KStack 0x%x", thread->CR3, thread->KernelStack); - } - Log("Sleeping Threads:"); - for(thread=gSleepingThreads;thread;thread=thread->Next) - { - Log(" %i (%i) - %s", thread->TID, thread->TGID, thread->ThreadName); - Log(" %i Tickets, Quantum %i", thread->NumTickets, thread->Quantum); - Log(" CR3 0x%x, KStack 0x%x", thread->CR3, thread->KernelStack); - } -} - -/** - * \fn void Proc_Scheduler(int CPU) - * \brief Swap current task - */ -void Proc_Scheduler(int CPU) -{ - Uint esp, ebp, eip; - Uint number, ticket; - tThread *thread; - - // Increment Timestamps - giTicks ++; - giTimestamp += MS_PER_TICK_WHOLE; - giPartMiliseconds += MS_PER_TICK_FRACT; - if(giPartMiliseconds > 0x80000000) { - giTimestamp ++; - giPartMiliseconds -= 0x80000000; - } - - // If the spinlock is set, let it complete - if(giThreadListLock) return; - - // Clear Delete Queue - while(gDeleteThreads) - { - thread = gDeleteThreads->Next; - if(gDeleteThreads->IsLocked) { // Only free if structure is unused - gDeleteThreads->Status = THREAD_STAT_NULL; - free( gDeleteThreads ); - } - gDeleteThreads = thread; - } - - // Check if there is any tasks running - if(giNumActiveThreads == 0) { - Log("No Active threads, sleeping\n"); - __asm__ __volatile__ ("hlt"); - return; - } - - // Reduce remaining quantum - if(gCurrentThread->Remaining--) return; - // Reset quantum for next call - gCurrentThread->Remaining = gCurrentThread->Quantum; - - // Get machine state - __asm__ __volatile__ ("mov %%esp, %0":"=r"(esp)); - __asm__ __volatile__ ("mov %%ebp, %0":"=r"(ebp)); - eip = GetEIP(); - if(eip == SWITCH_MAGIC) return; // Check if a switch happened - - // Save machine state - gCurrentThread->ESP = esp; - gCurrentThread->EBP = ebp; - gCurrentThread->EIP = eip; - - // Special case: 1 thread - if(giNumActiveThreads == 1) - { - // Check if a switch is needed (NumActive can be 1 after a sleep) - if(gActiveThreads == gCurrentThread) return; - // Switch processes - gCurrentThread = gActiveThreads; - goto performSwitch; - } - - // Get the ticket number - ticket = number = rand() % giTotalTickets; - - //Log(" Proc_Scheduler: number = 0x%x\n", number); - - // Find the next thread - for(thread=gActiveThreads;thread;thread=thread->Next) - { - if(thread->NumTickets > number) break; - number -= thread->NumTickets; - } - - // Error Check - if(thread == NULL) - { - number = 0; - for(thread=gActiveThreads;thread;thread=thread->Next) - number += thread->NumTickets; - Panic("Bookeeping Failed - giTotalTicketCount (%i) != true count (%i)", - giTotalTickets, number); - } - - // Set current thread - gCurrentThread = thread; - - // Update Kernel Stack pointer - gTSSs[CPU].ESP0 = thread->KernelStack; - -performSwitch: - // Set address space - MM_SetCR3( gCurrentThread->CR3 ); - // Switch threads - __asm__ __volatile__ ( - "mov %1, %%esp\n\t" - "mov %2, %%ebp\n\t" - "jmp *%3" : : - "a"(SWITCH_MAGIC), "b"(gCurrentThread->ESP), - "d"(gCurrentThread->EBP), "c"(gCurrentThread->EIP)); - for(;;); // Shouldn't reach here -} - -/** - * \fn Uint rand() - * \brief Pseudo random number generator - * \note Unknown effectiveness (made up on the spot) - */ -Uint rand() -{ - static Uint randomState = RANDOM_SEED; - Uint ret = randomState; - int roll = randomState & 31; - randomState = (randomState << roll) | (randomState >> (32-roll)); - randomState ^= 0x9A3C5E78; - return ret; -} diff --git a/Kernel/system.c b/Kernel/system.c index 4dc92c8b..27c35027 100644 --- a/Kernel/system.c +++ b/Kernel/system.c @@ -9,6 +9,7 @@ extern int Modules_LoadBuiltins(); extern int PCI_Install(); extern void DMA_Install(); +extern void Debug_SetKTerminal(char *File); // === PROTOTYPES === void System_Init(char *ArgString); @@ -29,6 +30,9 @@ void System_Init(char *ArgString) DMA_Install(); Modules_LoadBuiltins(); + // Set the debug to be echoed to the terminal + Debug_SetKTerminal("/Devices/vterm/0"); + // - Parse Kernel's Command Line System_ParseCommandLine(ArgString); diff --git a/Kernel/threads.c b/Kernel/threads.c index 3be97892..00fc0506 100644 --- a/Kernel/threads.c +++ b/Kernel/threads.c @@ -335,7 +335,7 @@ void Threads_AddToDelete(tThread *Thread) } /** - * \fn tThread *Threads_int_GetPrev(tThread *List, tThread *Thread) + * \fn tThread *Threads_int_GetPrev(tThread **List, tThread *Thread) * \brief Gets the previous entry in a thead linked list */ tThread *Threads_int_GetPrev(tThread **List, tThread *Thread) @@ -373,7 +373,8 @@ void Threads_Exit(int TID, int Status) /** * \fn void Threads_Kill(tThread *Thread, int Status) * \brief Kill a thread - * \param TID Thread ID (0 for current) + * \param Thread Thread to kill + * \param Status Status code to return to the parent */ void Threads_Kill(tThread *Thread, int Status) { diff --git a/Kernel/vfs.c b/Kernel/vfs.c deleted file mode 100644 index c1d6eef5..00000000 --- a/Kernel/vfs.c +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Acess 2 - * binary.c - * - Binary File Loader - */ -#include -#include - -// === GLOBALS === - - -// === CODE === diff --git a/Kernel/vfs/fs/devfs.c b/Kernel/vfs/fs/devfs.c index 6ead47e5..90770a75 100644 --- a/Kernel/vfs/fs/devfs.c +++ b/Kernel/vfs/fs/devfs.c @@ -43,7 +43,7 @@ int DevFS_AddDevice(tDevFS_Driver *Dev) /** * \fn tVFS_Node *DevFS_InitDevice(char *Device, char **Options) * \brief Initialise the DevFS and detect double-mounting, or just do nothing - * \stub + * \note STUB */ tVFS_Node *DevFS_InitDevice(char *Device, char **Options) { diff --git a/Kernel/vfs/fs/ext2.c b/Kernel/vfs/fs/ext2.c index 8ee26aff..be50e6ca 100644 --- a/Kernel/vfs/fs/ext2.c +++ b/Kernel/vfs/fs/ext2.c @@ -69,7 +69,7 @@ int Ext2_Install(char **Arguments) } /** - \fn tVFS_Node *Ext2_initDevice(char *Device, char **Options) + \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 @@ -336,7 +336,7 @@ addBlocks: } /** - * \fn void Ext2_CloseFile(vfs_node *Node) + * \fn void Ext2_CloseFile(tVFS_Node *Node) * \brief Close a file (Remove it from the cache) */ void Ext2_CloseFile(tVFS_Node *Node) @@ -487,11 +487,11 @@ int Ext2_MkNod(tVFS_Node *Parent, char *Name, Uint Flags) /** - \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 -*/ + * \fn int Ext2_int_GetInode(tVFS_Node *Node, tExt2_Inode *Inode) + * \brief Gets the inode descriptor for a node + * \param Node node to get the Inode of + * \param Inode Destination + */ int Ext2_int_GetInode(tVFS_Node *Node, tExt2_Inode *Inode) { return Ext2_int_ReadInode(Node->ImplPtr, Node->Inode, Inode); diff --git a/Kernel/vfs/fs/fat.c b/Kernel/vfs/fs/fat.c index 7c5eefcd..5712da91 100644 --- a/Kernel/vfs/fs/fat.c +++ b/Kernel/vfs/fs/fat.c @@ -36,7 +36,7 @@ tVFS_Node *FAT_FindDir(tVFS_Node *dirNode, char *file); void FAT_CloseFile(tVFS_Node *node); // === SEMI-GLOBALS === -MODULE_DEFINE(0, 0x51 /*v0.80*/, FAT32, FAT_Install, NULL); +MODULE_DEFINE(0, 0x51 /*v0.80*/, FAT32, FAT_Install, NULL, NULL); tFAT_VolInfo gFAT_Disks[8]; int giFAT_PartCount = 0; #if CACHE_FAT diff --git a/Kernel/vfs/fs/fs_ext2.h b/Kernel/vfs/fs/fs_ext2.h index 0041116e..f7c9ae15 100644 --- a/Kernel/vfs/fs/fs_ext2.h +++ b/Kernel/vfs/fs/fs_ext2.h @@ -1,8 +1,8 @@ /** - Acess Version 1 - \file fs_ext2_int.h - \brief EXT2 Filesystem Driver -*/ + * Acess2 + * \file fs_ext2.h + * \brief EXT2 Filesystem Driver + */ /** \name Inode Flag Values @@ -35,11 +35,16 @@ #define EXT2_NAME_LEN 255 //!< Maximum Name Length -//STRUCTURES +// === 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 + +// === STRUCTURES === /** - \struct ext2_super_block_s - \brief EXT2 Superblock Structure -*/ + * \brief EXT2 Superblock Structure + */ struct ext2_super_block_s { Uint32 s_inodes_count; //!< Inodes count Uint32 s_blocks_count; //!< Blocks count @@ -70,9 +75,9 @@ struct ext2_super_block_s { }; /** - \struct ext2_inode_s - \brief EXT2 Inode Definition -*/ + * \struct ext2_inode_s + * \brief EXT2 Inode Definition + */ struct ext2_inode_s { Uint16 i_mode; //!< File mode Uint16 i_uid; //!< Owner Uid @@ -120,9 +125,9 @@ struct ext2_inode_s { }; /** - \struct ext2_group_desc_s - \brief EXT2 Group Descriptor -*/ + * \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 @@ -135,10 +140,9 @@ struct ext2_group_desc_s { }; /** - \struct ext2_dir_entry - \brief EXT2 Directory Entry - \note The name may take up less than 255 characters -*/ + * \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 @@ -146,9 +150,3 @@ struct ext2_dir_entry_s { 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/Makefile.cfg b/Makefile.cfg index f6f00610..17524975 100644 --- a/Makefile.cfg +++ b/Makefile.cfg @@ -16,7 +16,7 @@ ARCHDIR = x86 FILESYSTEMS = fat ext2 DRIVERS = ata_x86 fdd -MODULES = ne2000 +MODULES = NE2000 BochsVBE DISTROOT = /mnt/AcessHDD/Acess2 ACESSDIR = /home/hodgeja/Projects/Acess2 diff --git a/Modules/BochsVBE/bochsvbe.c b/Modules/BochsVBE/bochsvbe.c index a55e702f..2fe01100 100644 --- a/Modules/BochsVBE/bochsvbe.c +++ b/Modules/BochsVBE/bochsvbe.c @@ -85,8 +85,8 @@ tDevFS_Driver gBGA_DriverStruct = { Uint *gBGA_Framebuffer; t_bga_mode gBGA_Modes[] = { {}, - { 80,25, 32, MODEFLAG_TEXT, 80*25*8}, // 640 x 480 - {100,37, 32, MODEFLAG_TEXT, 100*37*8}, // 800 x 600 + { 80,25, 12, MODEFLAG_TEXT, 80*25*8}, // 640 x 480 + {100,37, 12, MODEFLAG_TEXT, 100*37*8}, // 800 x 600 {640,480,8, 0, 640*480}, {640,480,32, 0, 640*480*4}, {800,600,8, 0, 800*600}, @@ -176,8 +176,10 @@ Uint64 BGA_Write(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer) tVT_Char *chars = buffer; int pitch = gBGA_Modes[giBGA_CurrentMode].width * giVT_CharWidth; Uint32 *dest; + off /= sizeof(tVT_Char); dest = (void*)gBGA_Framebuffer; - dest += off * giVT_CharWidth; + dest += (off / gBGA_Modes[giBGA_CurrentMode].width) * giVT_CharHeight * pitch; + dest += (off % gBGA_Modes[giBGA_CurrentMode].width) * giVT_CharWidth; len /= sizeof(tVT_Char); while(len--) { @@ -400,9 +402,9 @@ int BGA_int_FindMode(tVideo_IOCtl_Mode *info) int BGA_int_ModeInfo(tVideo_IOCtl_Mode *info) { // Sanity Check - if( !MM_IsUser( (Uint)info, sizeof(tVideo_IOCtl_Mode) ) ) { - return -EINVAL; - } + //if( !MM_IsUser( (Uint)info, sizeof(tVideo_IOCtl_Mode) ) ) { + // return -EINVAL; + //} if(info->id < 0 || info->id >= BGA_MODE_COUNT) return -1; diff --git a/Modules/Makefile.tpl b/Modules/Makefile.tpl index 6d22b4c3..41743443 100644 --- a/Modules/Makefile.tpl +++ b/Modules/Makefile.tpl @@ -9,21 +9,27 @@ CFLAGS = -Wall -Werror $(CPPFLAGS) OBJ := $(addsuffix .$(ARCH),$(OBJ)) BIN = ../$(NAME).kmd.$(ARCH) +KOBJ = ../$(NAME).xo.$(ARCH) + +DEPFILES = $(filter %.o.$(ARCH),$(OBJ)) +DEPFILES := $(DEPFILES:%.o.$(ARCH)=%.d.$(ARCH)) .PHONY: all clean all: $(BIN) clean: - $(RM) $(BIN) $(OBJ) + $(RM) $(BIN) $(KOBJ) $(OBJ) $(DEPFILES) $(BIN): $(OBJ) @echo --- $(LD) -o $@ @$(LD) -T ../link.ld -shared -o $@ $(OBJ) @echo --- $(LD) -o ../$(NAME).o.$(ARCH) - @$(CC) -Wl,-r -nostdlib -o ../$(NAME).o.$(ARCH) $(OBJ) + @$(CC) -Wl,-r -nostdlib -o $(KOBJ) $(OBJ) %.o.$(ARCH): %.c Makefile ../Makefile.tpl ../../Makefile.cfg @echo --- $(CC) -o $@ @$(CC) $(CFLAGS) -o $@ -c $< - @$(CC) -M $(CPPFLAGS) -MT $@ -o $*.d $< + @$(CC) -M $(CPPFLAGS) -MT $@ -o $*.d.$(ARCH) $< + +-include $(DEPFILES) diff --git a/Modules/NE2000/Makefile b/Modules/NE2000/Makefile index f6f34859..7e740227 100644 --- a/Modules/NE2000/Makefile +++ b/Modules/NE2000/Makefile @@ -2,6 +2,6 @@ # OBJ = ne2000.o -NAME = ne2000 +NAME = NE2000 -include ../Makefile.tpl diff --git a/Usermode/Applications/CLIShell_src/main.c b/Usermode/Applications/CLIShell_src/main.c index d6c40d65..836c6f50 100644 --- a/Usermode/Applications/CLIShell_src/main.c +++ b/Usermode/Applications/CLIShell_src/main.c @@ -135,7 +135,9 @@ char *ReadCommandLine(int *Length) char *ret; int len, pos, space = 1023; char ch; - // int scrollbackPos = giLastCommand; + #if 1 + int scrollbackPos = giLastCommand; + #endif // Preset Variables ret = malloc( space+1 ); @@ -145,8 +147,13 @@ char *ReadCommandLine(int *Length) // Read In Command Line do { read(_stdin, 1, &ch); // Read Character from stdin (read is a blocking call) + + if(ch == '\n') break; + + switch(ch) + { // Control characters - if(ch == '\x1B') { + case '\x1B': read(_stdin, 1, &ch); // Read control character switch(ch) { @@ -158,23 +165,32 @@ char *ReadCommandLine(int *Length) { #if 0 case 'A': // Up - if( scrollbackPos > 0 ) break; - - free(ret); - ret = strdup( gasCommandHistory[--scrollbackPos] ); - - len = strlen(ret); - while(pos--) write(_stdout, 3, "\x1B[D"); - while(pos++ < len) write(_stdout, 3, "\x1B[C"); + { + int oldLen = len; + if( scrollbackPos > 0 ) break; + + free(ret); + ret = strdup( gasCommandHistory[--scrollbackPos] ); + + len = strlen(ret); + while(pos--) write(_stdout, 3, "\x1B[D"); + write(_stdout, len, ret); pos = len; + while(pos++ < oldLen) write(_stdout, 1, " "); + } break; case 'B': // Down - if( scrollbackPos < giLastCommand-1 ) break; - free(ret); - ret = strdup( gasCommandHistory[++scrollbackPos] ); - - len = strlen(ret); - while(pos--) write(_stdout, 3, "\x1B[D"); - while(pos++ < len) write(_stdout, 3, "\x1B[C"); + { + int oldLen = len; + if( scrollbackPos < giLastCommand-1 ) break; + + free(ret); + ret = strdup( gasCommandHistory[++scrollbackPos] ); + + len = strlen(ret); + while(pos--) write(_stdout, 3, "\x1B[D"); + write(_stdout, len, ret); pos = len; + while(pos++ < oldLen) write(_stdout, 1, " "); + } break; #endif case 'D': // Left @@ -183,49 +199,74 @@ char *ReadCommandLine(int *Length) write(_stdout, 3, "\x1B[D"); break; case 'C': // Right - if(pos == len-1) break; + if(pos == len) break; pos++; write(_stdout, 3, "\x1B[C"); break; } } - continue; - } + break; + // Backspace - if(ch == '\b') { - if(len <= 0) continue; // Protect against underflows + case '\b': + if(len <= 0) break; // Protect against underflows + write(_stdout, 1, &ch); if(pos == len) { // Simple case of end of string - len --; pos--; - } else { + len --; + pos--; + } + else { + char buf[7] = "\x1B[000D"; + buf[2] += ((len-pos+1)/100) % 10; + buf[3] += ((len-pos+1)/10) % 10; + buf[4] += (len-pos+1) % 10; + write(_stdout, len-pos, &ret[pos]); // Move Text + ch = ' '; write(_stdout, 1, &ch); ch = '\b'; // Clear deleted character + write(_stdout, 7, buf); // Update Cursor + // Alter Buffer memmove(&ret[pos-1], &ret[pos], len-pos); pos --; len --; } - write(_stdout, 1, &ch); - continue; - } + break; + // Tab - if(ch == '\t') { + case '\t': //TODO: Implement Tab-Completion //Currently just ignore tabs - continue; - } + break; - // Expand Buffer - if(len > space) { - space += 256; - ret = realloc(ret, space+1); - if(!ret) return NULL; + default: + // Expand Buffer + if(len+1 > space) { + space += 256; + ret = realloc(ret, space+1); + if(!ret) return NULL; + } + + // Editing inside the buffer + if(pos != len) { + char buf[7] = "\x1B[000D"; + buf[2] += ((len-pos)/100) % 10; + buf[3] += ((len-pos)/10) % 10; + buf[4] += (len-pos) % 10; + write(_stdout, 1, &ch); // Print new character + write(_stdout, len-pos, &ret[pos]); // Move Text + write(_stdout, 7, buf); // Update Cursor + memmove( &ret[pos+1], &ret[pos], len-pos ); + } + else { + write(_stdout, 1, &ch); + } + ret[pos++] = ch; + len ++; + break; } - - write(_stdout, 1, &ch); - ret[pos++] = ch; - len ++; } while(ch != '\n'); - // Remove newline - pos --; - ret[pos] = '\0'; + // Cap String + ret[len] = '\0'; + printf("\n"); // Return length if(Length) *Length = len; diff --git a/Usermode/Applications/init_src/main.c b/Usermode/Applications/init_src/main.c index 8787f39c..3473eb51 100644 --- a/Usermode/Applications/init_src/main.c +++ b/Usermode/Applications/init_src/main.c @@ -5,28 +5,35 @@ // === CONSTANTS === #define NULL ((void*)0) +#define NUM_TERMS 4 #define DEFAULT_TERMINAL "/Devices/VTerm/0" #define DEFAULT_SHELL "/Acess/SBin/login" // === CODE === /** * \fn int main(int argc, char *argv[]) + * \brief Entrypoint */ int main(int argc, char *argv[]) { int tid; - open(DEFAULT_TERMINAL, OPENFLAG_READ); // Stdin - open(DEFAULT_TERMINAL, OPENFLAG_WRITE); // Stdout - open(DEFAULT_TERMINAL, OPENFLAG_WRITE); // Stderr + // int i; + char termpath[sizeof(DEFAULT_TERMINAL)+1] = DEFAULT_TERMINAL; - write(1, 13, "Hello, World!"); - - tid = clone(CLONE_VM, 0); - if(tid == 0) - { - execve(DEFAULT_SHELL, NULL, NULL); - for(;;) __asm__ __volatile__("hlt"); - } + //for( i = 0; i < NUM_TERMS; i++ ) + //{ + //termpath[ sizeof(DEFAULT_TERMINAL)-1 ] = '0' + i; + open(termpath, OPENFLAG_READ); // Stdin + open(termpath, OPENFLAG_WRITE); // Stdout + open(termpath, OPENFLAG_WRITE); // Stderr + + tid = clone(CLONE_VM, 0); + if(tid == 0) + { + execve(DEFAULT_SHELL, NULL, NULL); + for(;;) __asm__ __volatile__("hlt"); + } + //} for(;;) sleep(); diff --git a/Usermode/Applications/login_src/main.c b/Usermode/Applications/login_src/main.c index 248e13b9..391d5bcc 100644 --- a/Usermode/Applications/login_src/main.c +++ b/Usermode/Applications/login_src/main.c @@ -22,11 +22,19 @@ int main(int argc, char *argv[]) { printf("\x1B[2J"); // Clear Screen // Validate User - do { - if(uid == -1) printf("\n"); + for(;;) + { sUsername = GetUsername(); sPassword = GetPassword(); - } while( (uid = ValidateUser(sUsername, sPassword)) == -1 ); + if( (uid = ValidateUser(sUsername, sPassword)) == -1 ) + { + printf("\nInvalid username or password for '%s'\n", sUsername); + free(sUsername); + free(sPassword); + } + else + break; + } printf("\n"); // Create child process @@ -67,7 +75,7 @@ int main(int argc, char *argv[]) */ char *GetUsername() { - char ret[BUFLEN]; + char ret[BUFLEN] = {0}; int pos = 0; char ch; diff --git a/Usermode/Libraries/libc.so_src/fileIO.c b/Usermode/Libraries/libc.so_src/fileIO.c index 1645cde2..5fdac4cc 100644 --- a/Usermode/Libraries/libc.so_src/fileIO.c +++ b/Usermode/Libraries/libc.so_src/fileIO.c @@ -29,9 +29,9 @@ struct sFILE *stderr; // Standard Error // === CODE === /** - * \fn FILE *freopen(FILE *fp, char *file, char *mode) + * \fn FILE *freopen(char *file, char *mode, FILE *fp) */ -EXPORT FILE *freopen(FILE *fp, char *file, char *mode) +EXPORT FILE *freopen(const char *file, const char *mode, FILE *fp) { int openFlags = 0; int i; @@ -98,12 +98,12 @@ EXPORT FILE *freopen(FILE *fp, char *file, char *mode) return fp; } /** - \fn FILE *fopen(char *file, char *mode) + \fn FILE *fopen(const char *file, const char *mode) \brief Opens a file and returns the pointer \param file String - Filename to open \param mode Mode to open in */ -EXPORT FILE *fopen(char *file, char *mode) +EXPORT FILE *fopen(const char *file, const char *mode) { FILE *retFile; @@ -113,7 +113,7 @@ EXPORT FILE *fopen(char *file, char *mode) // Create Return Structure retFile = get_file_struct(); - return freopen(retFile, file, mode); + return freopen(file, mode, retFile); } EXPORT void fclose(FILE *fp) diff --git a/Usermode/Libraries/libc.so_src/string.c b/Usermode/Libraries/libc.so_src/string.c index 07c20179..98692b21 100644 --- a/Usermode/Libraries/libc.so_src/string.c +++ b/Usermode/Libraries/libc.so_src/string.c @@ -34,6 +34,35 @@ EXPORT char *strcpy(char *dst, const char *src) return _dst; } +/** + * \fn EXPORT char *strncpy(char *dst, const char *src) + * \brief Copy at most \a num characters from \a src to \a dst + * \return \a dst + */ +EXPORT char *strncpy(char *dst, const char *src, size_t num) +{ + char *to = dst; + while(*src && num--) *to++ = *src++; + *to = '\0'; + return dst; +} + +/** + * \fn EXPORT char *strcat(char *dst, const char *src) + * \brief Append a string onto another + */ +EXPORT char *strcat(char *dst, const char *src) +{ + char *to = dst; + // Find the end + while(*to) to++; + // Copy + while(*src) *to++ = *src++; + // End string + *to = '\0'; + return dst; +} + /** * \fn EXPORT int strlen(const char *str) * \brief Get the length of a string @@ -72,6 +101,52 @@ EXPORT char *strdup(const char *str) return ret; } +/** + * \fn EXPORT char *strchr(char *str, int character) + * \brief Locate a character in a string + */ +EXPORT char *strchr(char *str, int character) +{ + while(*str) + { + if(*str == character) return str; + } + return NULL; +} + +/** + * \fn EXPORT char *strrchr(char *str, int character) + * \brief Locate the last occurance of a character in a string + */ +EXPORT char *strrchr(char *str, int character) +{ + int i; + i = strlen(str)-1; + while(i--) + { + if(str[i] == character) return &str[i]; + } + return NULL; +} + +/** + * \fn EXPORT char *strstr(char *str1, const char *str2) + * \brief Search a \a str1 for the first occurance of \a str2 + */ +EXPORT char *strstr(char *str1, const char *str2) +{ + const char *test = str2; + + while(*str1) + { + if(*test == '\0') return str1; + if(*str1 == *test) test++; + else test = str2; + str1 ++; + } + return NULL; +} + // --- Memory --- /** * \fn EXPORT void *memset(void *dest, int val, size_t num) @@ -111,3 +186,40 @@ EXPORT void *memmove(void *dest, const void *src, size_t count) for(;count--;) *dp++ = *sp++; return dest; } + +/** + * \fn EXPORT int memcmp(const void *mem1, const void *mem2, size_t count) + * \brief Compare two regions of memory + * \param mem1 Region 1 + * \param mem2 Region 2 + * \param count Number of bytes to check + */ +EXPORT int memcmp(const void *mem1, const void *mem2, size_t count) +{ + while(count--) + { + if( *(unsigned char*)mem1 != *(unsigned char*)mem2 ) + return *(unsigned char*)mem1 - *(unsigned char*)mem2; + mem1 ++; + mem2 ++; + } + return 0; +} + +/** + * \fn EXPORT void *memchr(void *ptr, int value, size_t num) + * \brief Locates the first occurence of \a value starting at \a ptr + * \param ptr Starting memory location + * \param value Value to find + * \param num Size of memory area to check + */ +EXPORT void *memchr(void *ptr, int value, size_t num) +{ + while(num--) + { + if( *(unsigned char*)ptr == (unsigned char)value ) + return ptr; + ptr ++; + } + return NULL; +} diff --git a/Usermode/include/acess/sys.h b/Usermode/include/acess/sys.h index d1e39aff..a1bdbbbf 100644 --- a/Usermode/include/acess/sys.h +++ b/Usermode/include/acess/sys.h @@ -71,9 +71,9 @@ extern void setuid(int id); extern void setgid(int id); // --- VFS --- -extern int chdir(char *dir); -extern int open(char *path, int flags); -extern int reopen(int fd, char *path, int flags); +extern int chdir(const char *dir); +extern int open(const char *path, int flags); +extern int reopen(int fd, const char *path, int flags); extern void close(int fd); extern uint64_t read(int fd, uint64_t length, void *buffer); extern uint64_t write(int fd, uint64_t length, void *buffer); @@ -83,7 +83,7 @@ extern int ioctl(int fd, int id, void *data); extern int finfo(int fd, t_sysFInfo *info, int maxacls); extern int readdir(int fd, char *dest); extern int _SysGetACL(int fd, t_sysACL *dest); -extern int _SysMount(char *Device, char *Directory, char *Type, char *Options); +extern int _SysMount(const char *Device, const char *Directory, const char *Type, const char *Options); // --- IPC --- extern int SysSendMessage(int dest, int length, void *Data); diff --git a/Usermode/include/stdio.h b/Usermode/include/stdio.h index 26d9c683..985f058c 100644 --- a/Usermode/include/stdio.h +++ b/Usermode/include/stdio.h @@ -7,15 +7,21 @@ #include #include - + +// === Types === typedef struct sFILE FILE; +// === CONSTANTS === +#define EOF (-1) + +// --- Standard IO --- extern int printf(const char *format, ...); extern int vsprintf(char *buf, const char *format, va_list args); -extern int sprintf(char *buf, const char *format, ...); +extern int sprintf(char *buf, const char *format, ...); -extern FILE *fopen(char *file, char *mode); -extern FILE *freopen(FILE *fp, char *file, char *mode); +extern FILE *fopen(const char *file, const char *mode); +extern FILE *freopen(const char *file, const char *mode, FILE *fp); +extern FILE *fdopen(int fd, const char *modes); extern void fclose(FILE *fp); extern void fflush(FILE *fp); extern long int ftell(FILE *fp); diff --git a/Usermode/include/stdlib.h b/Usermode/include/stdlib.h index 9dd720e7..50cedb34 100644 --- a/Usermode/include/stdlib.h +++ b/Usermode/include/stdlib.h @@ -1,23 +1,17 @@ /* -AcessOS LibC - -stdlib.h -*/ + * AcessOS LibC + * stdlib.h + */ #ifndef __STDLIB_H #define __STDLIB_H +#include #include #include -#ifndef NULL -# define NULL ((void*)0) -#endif - #define EXIT_FAILURE 1 #define EXIT_SUCCESS 0 -typedef unsigned int size_t; - // --- Spinlock Macros --- #define DEFLOCK(_name) static int _spinlock_##_name=0; //#define LOCK(_name) __asm__ __volatile__("jmp ._tst;\n\t._lp:call yield;\n\t._tst:lock btsl $1,(%0);\n\tjc ._lp"::"D"(&_spinlock_##_name)) @@ -25,6 +19,7 @@ typedef unsigned int size_t; #define UNLOCK(_name) __asm__ __volatile__("lock andl $0, (%0)"::"D"(&_spinlock_##_name)) // --- StdLib --- +extern void _exit(int code); //NOTE: Also defined in acess/sys.h extern int atoi(const char *ptr); extern void exit(int status) __attribute__((noreturn)); extern void qsort(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *)); diff --git a/Usermode/include/string.h b/Usermode/include/string.h index beeff608..1e721974 100644 --- a/Usermode/include/string.h +++ b/Usermode/include/string.h @@ -5,19 +5,25 @@ #ifndef __STRING_H #define __STRING_H -#include - -// 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); +#include // 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 *strncpy(char *dst, const char *src, size_t num); +extern char *strcat(char *dst, const char *src); extern char *strdup(const char *src); +extern char *strchr(char *str, int character); +extern char *strrchr(char *str, int character); +extern char *strstr(char *str1, const char *str2); + +// 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); +extern void *memchr(void *ptr, int value, size_t num); #endif -- 2.20.1