- 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
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))
@$(MAKEDEP) $(CPPFLAGS) -MT $@ -o $*.d.$(ARCH) $<
# endif
+%.xo.$(ARCH):
+ @make -C $* all
+
include/syscalls.h: syscalls.lst Makefile
php GenSyscalls.php
}
/**
- * \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)
{
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)
{
}
/**
- * \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)
/**
- * \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)
* \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)
{
inb(0x71); // Just throw away contents.
}
+#if 0
/**
* \fn void Time_TimerThread()
*/
-#if 0
void Time_TimerThread()
{
Sint64 next;
#include <common.h>
#include <stdarg.h>
-// === 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++);
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;
NULL, "PS2Keyboard",
{
.NumACLs = 0,
- .Size = -1,
- .Read = KB_Read,
+ .Size = 0,
+ //.Read = KB_Read,
.IOCtl = KB_IOCtl
}
};
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;
}
}
// 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])
{
switch(ch)
{
+ case 0: break;
case '`': ch = '~'; break;
case '1': ch = '!'; break;
case '2': ch = '@'; break;
}
}
- 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);
}
/**
/*E0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
/*F0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
};\r
+// - 0xE1 Prefixed\r
Uint8 gpKBDUS3[256] = {\r
// 0 1 2 3 4 5 6 7 8 9 A B C D E F\r
/*00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0-F\r
#include <modules.h>
#include <tpl_drv_video.h>
#include <tpl_drv_keyboard.h>
+#include <tpl_drv_terminal.h>
+#include <errno.h>
// === 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;
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);
};
// === 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",
{
.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 ===
/**
}
// 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);
// 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;
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
{
giVT_OutputDevHandle = VFS_Open(gsVT_OutputDevice, VFS_OPENFLAG_WRITE);
LOG("giVT_OutputDevHandle = %x\n", giVT_OutputDevHandle);
+ VT_SetTerminal( 0 );
}
/**
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
// 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;
// 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);
}
/**
- * \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
{
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;
+ }
}
}
{
char c;
int argc = 0, j = 1;
+ int tmp;
int args[4] = {0,0,0,0};
switch(Buffer[0]) {
args[argc] += c-'0';
c = Buffer[++j];
}
- argc ++;
+ if( j != 1 ) argc ++;
} while(c == ';');
// Get string (what does this do?)
// 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])
# 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;
struct sModule *Next;
char *Name;
int (*Init)(char **Arguments);
+ void (*Deinit)();
char **Dependencies; // NULL Terminated List
} __attribute__((packed)) tModule;
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
"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",
%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
KEY_ESC = 0x1B,\r
\r
KEY_NP_MASK = 0x80, //End of ASCII Range\r
- KEY_LCTRL, KEY_RCTRL,\r
- KEY_LALT, KEY_RALT,\r
- KEY_LSHIFT, KEY_RSHIFT,\r
+ \r
KEY_CAPSLOCK,\r
KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT,\r
KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, \r
KEY_KPEND, KEY_KPDOWN, KEY_KPPGDN, KEY_KPINS, KEY_KPDEL,\r
KEY_WIN, KEY_MENU,\r
\r
+ // Modifiers\r
+ KEY_MODIFIERS = 0xC0,\r
+ KEY_LCTRL, KEY_RCTRL,\r
+ KEY_LALT, KEY_RALT,\r
+ KEY_LSHIFT, KEY_RSHIFT,\r
+ \r
KEY_KEYUP = 0xFF\r
};\r
\r
Uint8 bpp; //!< Bits per Pixel\r
Uint8 flags; //!< Mode Flags\r
};\r
-#define VIDEO_FLAG_TEXT 0x1 //!< Text Mode\r
+typedef struct sVideo_IOCtl_Mode tVideo_IOCtl_Mode; //!< Mode Type\r
+/**\r
+ * \brief Text Mode Flag\r
+ * \note A text mode should have the ::sVideo_IOCtl_Mode.bpp set to 12\r
+ */\r
+#define VIDEO_FLAG_TEXT 0x1\r
#define VIDEO_FLAG_SLOW 0x2 //!< Non-accelerated mode\r
+\r
+typedef struct sVideo_IOCtl_Pos tVideo_IOCtl_Pos; //!< Position Type\r
/**\r
*/\r
struct sVideo_IOCtl_Pos {\r
- Sint16 x;\r
- Sint16 y;\r
+ Sint16 x; //!< X Coordinate\r
+ Sint16 y; //!< Y Coordinate\r
};\r
-typedef struct sVideo_IOCtl_Mode tVideo_IOCtl_Mode; //!< Mode Type\r
-typedef struct sVideo_IOCtl_Pos tVideo_IOCtl_Pos; //!< Mode Type\r
\r
/**\r
* \struct sVT_Char\r
}
/**
- * \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)
* \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)
{
/**
* \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)
{
+++ /dev/null
-/*
- * AcessOS Microkernel Version
- * proc.c
- */
-#include <common.h>
-#include <proc.h>
-#include <mm_virt.h>
-#include <errno.h>
-#include <mp.h>
-
-// === 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<giNumCPUs;pos++)
- {
- gTSSs[pos].SS0 = 0x10;
- gTSSs[pos].ESP0 = 0; // Set properly by scheduler
- gGDT[9+pos].LimitLow = sizeof(tTSS);
- gGDT[9+pos].LimitHi = 0;
- gGDT[9+pos].Access = 0x89; // Type
- gGDT[9+pos].Flags = 0x4;
- gGDT[9+pos].BaseLow = (Uint)&gTSSs[pos] & 0xFFFF;
- gGDT[9+pos].BaseMid = (Uint)&gTSSs[pos] >> 16;
- gGDT[9+pos].BaseHi = (Uint)&gTSSs[pos] >> 24;
- }
- for(pos=0;pos<giNumCPUs;pos++) {
- __asm__ __volatile__ ("ltr %%ax"::"a"(0x48+pos*8));
- }
-
- // Set timer frequency
- outb(0x43, 0x34); // Set Channel 0, Low/High, Rate Generator
- outb(0x40, TIMER_DIVISOR&0xFF); // Low Byte of Divisor
- outb(0x40, (TIMER_DIVISOR>>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;
-}
extern int Modules_LoadBuiltins();
extern int PCI_Install();
extern void DMA_Install();
+extern void Debug_SetKTerminal(char *File);
// === PROTOTYPES ===
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);
}
/**
- * \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)
/**
* \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)
{
+++ /dev/null
-/*
- * Acess 2
- * binary.c
- * - Binary File Loader
- */
-#include <common.h>
-#include <vfs.h>
-
-// === GLOBALS ===
-
-
-// === CODE ===
/**
* \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)
{
}\r
\r
/**\r
- \fn tVFS_Node *Ext2_initDevice(char *Device, char **Options)\r
+ \fn tVFS_Node *Ext2_InitDevice(char *Device, char **Options)\r
\brief Initializes a device to be read by by the driver\r
\param Device String - Device to read from\r
\param Options NULL Terminated array of option strings\r
}\r
\r
/**\r
- * \fn void Ext2_CloseFile(vfs_node *Node)\r
+ * \fn void Ext2_CloseFile(tVFS_Node *Node)\r
* \brief Close a file (Remove it from the cache)\r
*/\r
void Ext2_CloseFile(tVFS_Node *Node)\r
\r
\r
/**\r
- \fn int Ext2_int_GetInode(vfs_node *Node, tExt2_Inode *Inode)\r
- \brief Gets the inode descriptor for a node\r
- \param node node to get the Inode of\r
- \param inode Destination\r
-*/\r
+ * \fn int Ext2_int_GetInode(tVFS_Node *Node, tExt2_Inode *Inode)\r
+ * \brief Gets the inode descriptor for a node\r
+ * \param Node node to get the Inode of\r
+ * \param Inode Destination\r
+ */\r
int Ext2_int_GetInode(tVFS_Node *Node, tExt2_Inode *Inode)\r
{\r
return Ext2_int_ReadInode(Node->ImplPtr, Node->Inode, Inode);\r
void FAT_CloseFile(tVFS_Node *node);\r
\r
// === SEMI-GLOBALS ===\r
-MODULE_DEFINE(0, 0x51 /*v0.80*/, FAT32, FAT_Install, NULL);\r
+MODULE_DEFINE(0, 0x51 /*v0.80*/, FAT32, FAT_Install, NULL, NULL);\r
tFAT_VolInfo gFAT_Disks[8];\r
int giFAT_PartCount = 0;\r
#if CACHE_FAT\r
/**\r
- Acess Version 1\r
- \file fs_ext2_int.h\r
- \brief EXT2 Filesystem Driver\r
-*/\r
+ * Acess2\r
+ * \file fs_ext2.h\r
+ * \brief EXT2 Filesystem Driver\r
+ */\r
\r
/**\r
\name Inode Flag Values\r
\r
#define EXT2_NAME_LEN 255 //!< Maximum Name Length\r
\r
-//STRUCTURES\r
+// === TYPEDEFS ===\r
+typedef struct ext2_inode_s tExt2_Inode; //!< Inode Type\r
+typedef struct ext2_super_block_s tExt2_SuperBlock; //!< Superblock Type\r
+typedef struct ext2_group_desc_s tExt2_Group; //!< Group Descriptor Type\r
+typedef struct ext2_dir_entry_s tExt2_DirEnt; //!< Directory Entry Type\r
+\r
+// === STRUCTURES ===\r
/**\r
- \struct ext2_super_block_s\r
- \brief EXT2 Superblock Structure\r
-*/\r
+ * \brief EXT2 Superblock Structure\r
+ */\r
struct ext2_super_block_s {\r
Uint32 s_inodes_count; //!< Inodes count\r
Uint32 s_blocks_count; //!< Blocks count\r
};\r
\r
/**\r
- \struct ext2_inode_s\r
- \brief EXT2 Inode Definition\r
-*/\r
+ * \struct ext2_inode_s\r
+ * \brief EXT2 Inode Definition\r
+ */\r
struct ext2_inode_s {\r
Uint16 i_mode; //!< File mode\r
Uint16 i_uid; //!< Owner Uid\r
};\r
\r
/**\r
- \struct ext2_group_desc_s\r
- \brief EXT2 Group Descriptor\r
-*/\r
+ * \struct ext2_group_desc_s\r
+ * \brief EXT2 Group Descriptor\r
+ */\r
struct ext2_group_desc_s {\r
Uint32 bg_block_bitmap; //!< Blocks bitmap block\r
Uint32 bg_inode_bitmap; //!< Inodes bitmap block\r
};\r
\r
/**\r
- \struct ext2_dir_entry\r
- \brief EXT2 Directory Entry\r
- \note The name may take up less than 255 characters\r
-*/\r
+ * \brief EXT2 Directory Entry\r
+ * \note The name may take up less than 255 characters\r
+ */\r
struct ext2_dir_entry_s {\r
Uint32 inode; //!< Inode number\r
Uint16 rec_len; //!< Directory entry length\r
Uint8 type; //!< File Type\r
char name[]; //!< File name\r
};\r
-\r
-//TYPEDEFS\r
-typedef struct ext2_inode_s tExt2_Inode; //!< Inode Type\r
-typedef struct ext2_super_block_s tExt2_SuperBlock; //!< Superblock Type\r
-typedef struct ext2_group_desc_s tExt2_Group; //!< Group Descriptor Type\r
-typedef struct ext2_dir_entry_s tExt2_DirEnt; //!< Directory Entry Type\r
FILESYSTEMS = fat ext2
DRIVERS = ata_x86 fdd
-MODULES = ne2000
+MODULES = NE2000 BochsVBE
DISTROOT = /mnt/AcessHDD/Acess2
ACESSDIR = /home/hodgeja/Projects/Acess2
Uint *gBGA_Framebuffer;\r
t_bga_mode gBGA_Modes[] = {\r
{},\r
- { 80,25, 32, MODEFLAG_TEXT, 80*25*8}, // 640 x 480\r
- {100,37, 32, MODEFLAG_TEXT, 100*37*8}, // 800 x 600\r
+ { 80,25, 12, MODEFLAG_TEXT, 80*25*8}, // 640 x 480\r
+ {100,37, 12, MODEFLAG_TEXT, 100*37*8}, // 800 x 600\r
{640,480,8, 0, 640*480},\r
{640,480,32, 0, 640*480*4},\r
{800,600,8, 0, 800*600},\r
tVT_Char *chars = buffer;\r
int pitch = gBGA_Modes[giBGA_CurrentMode].width * giVT_CharWidth;\r
Uint32 *dest;\r
+ off /= sizeof(tVT_Char);\r
dest = (void*)gBGA_Framebuffer;\r
- dest += off * giVT_CharWidth;\r
+ dest += (off / gBGA_Modes[giBGA_CurrentMode].width) * giVT_CharHeight * pitch;\r
+ dest += (off % gBGA_Modes[giBGA_CurrentMode].width) * giVT_CharWidth;\r
len /= sizeof(tVT_Char);\r
while(len--)\r
{\r
int BGA_int_ModeInfo(tVideo_IOCtl_Mode *info)\r
{\r
// Sanity Check\r
- if( !MM_IsUser( (Uint)info, sizeof(tVideo_IOCtl_Mode) ) ) {\r
- return -EINVAL;\r
- }\r
+ //if( !MM_IsUser( (Uint)info, sizeof(tVideo_IOCtl_Mode) ) ) {\r
+ // return -EINVAL;\r
+ //}\r
\r
if(info->id < 0 || info->id >= BGA_MODE_COUNT) return -1;\r
\r
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)
#
OBJ = ne2000.o
-NAME = ne2000
+NAME = NE2000
-include ../Makefile.tpl
char *ret;\r
int len, pos, space = 1023;\r
char ch;\r
- // int scrollbackPos = giLastCommand;\r
+ #if 1\r
+ int scrollbackPos = giLastCommand;\r
+ #endif\r
\r
// Preset Variables\r
ret = malloc( space+1 );\r
// Read In Command Line\r
do {\r
read(_stdin, 1, &ch); // Read Character from stdin (read is a blocking call)\r
+ \r
+ if(ch == '\n') break;\r
+ \r
+ switch(ch)\r
+ {\r
// Control characters\r
- if(ch == '\x1B') {\r
+ case '\x1B':\r
read(_stdin, 1, &ch); // Read control character\r
switch(ch)\r
{\r
{\r
#if 0\r
case 'A': // Up\r
- if( scrollbackPos > 0 ) break;\r
- \r
- free(ret);\r
- ret = strdup( gasCommandHistory[--scrollbackPos] );\r
- \r
- len = strlen(ret);\r
- while(pos--) write(_stdout, 3, "\x1B[D");\r
- while(pos++ < len) write(_stdout, 3, "\x1B[C");\r
+ {\r
+ int oldLen = len;\r
+ if( scrollbackPos > 0 ) break;\r
+ \r
+ free(ret);\r
+ ret = strdup( gasCommandHistory[--scrollbackPos] );\r
+ \r
+ len = strlen(ret);\r
+ while(pos--) write(_stdout, 3, "\x1B[D");\r
+ write(_stdout, len, ret); pos = len;\r
+ while(pos++ < oldLen) write(_stdout, 1, " ");\r
+ }\r
break;\r
case 'B': // Down\r
- if( scrollbackPos < giLastCommand-1 ) break;\r
- free(ret);\r
- ret = strdup( gasCommandHistory[++scrollbackPos] );\r
- \r
- len = strlen(ret);\r
- while(pos--) write(_stdout, 3, "\x1B[D");\r
- while(pos++ < len) write(_stdout, 3, "\x1B[C");\r
+ {\r
+ int oldLen = len;\r
+ if( scrollbackPos < giLastCommand-1 ) break;\r
+ \r
+ free(ret);\r
+ ret = strdup( gasCommandHistory[++scrollbackPos] );\r
+ \r
+ len = strlen(ret);\r
+ while(pos--) write(_stdout, 3, "\x1B[D");\r
+ write(_stdout, len, ret); pos = len;\r
+ while(pos++ < oldLen) write(_stdout, 1, " ");\r
+ }\r
break;\r
#endif\r
case 'D': // Left\r
write(_stdout, 3, "\x1B[D");\r
break;\r
case 'C': // Right\r
- if(pos == len-1) break;\r
+ if(pos == len) break;\r
pos++;\r
write(_stdout, 3, "\x1B[C");\r
break;\r
}\r
}\r
- continue;\r
- }\r
+ break;\r
+ \r
// Backspace\r
- if(ch == '\b') {\r
- if(len <= 0) continue; // Protect against underflows\r
+ case '\b':\r
+ if(len <= 0) break; // Protect against underflows\r
+ write(_stdout, 1, &ch);\r
if(pos == len) { // Simple case of end of string\r
- len --; pos--;\r
- } else {\r
+ len --;\r
+ pos--;\r
+ }\r
+ else {\r
+ char buf[7] = "\x1B[000D";\r
+ buf[2] += ((len-pos+1)/100) % 10;\r
+ buf[3] += ((len-pos+1)/10) % 10;\r
+ buf[4] += (len-pos+1) % 10;\r
+ write(_stdout, len-pos, &ret[pos]); // Move Text\r
+ ch = ' '; write(_stdout, 1, &ch); ch = '\b'; // Clear deleted character\r
+ write(_stdout, 7, buf); // Update Cursor\r
+ // Alter Buffer\r
memmove(&ret[pos-1], &ret[pos], len-pos);\r
pos --;\r
len --;\r
}\r
- write(_stdout, 1, &ch);\r
- continue;\r
- }\r
+ break;\r
+ \r
// Tab\r
- if(ch == '\t') {\r
+ case '\t':\r
//TODO: Implement Tab-Completion\r
//Currently just ignore tabs\r
- continue;\r
- }\r
+ break;\r
\r
- // Expand Buffer\r
- if(len > space) {\r
- space += 256;\r
- ret = realloc(ret, space+1);\r
- if(!ret) return NULL;\r
+ default: \r
+ // Expand Buffer\r
+ if(len+1 > space) {\r
+ space += 256;\r
+ ret = realloc(ret, space+1);\r
+ if(!ret) return NULL;\r
+ }\r
+ \r
+ // Editing inside the buffer\r
+ if(pos != len) {\r
+ char buf[7] = "\x1B[000D";\r
+ buf[2] += ((len-pos)/100) % 10;\r
+ buf[3] += ((len-pos)/10) % 10;\r
+ buf[4] += (len-pos) % 10;\r
+ write(_stdout, 1, &ch); // Print new character\r
+ write(_stdout, len-pos, &ret[pos]); // Move Text\r
+ write(_stdout, 7, buf); // Update Cursor\r
+ memmove( &ret[pos+1], &ret[pos], len-pos );\r
+ }\r
+ else {\r
+ write(_stdout, 1, &ch);\r
+ }\r
+ ret[pos++] = ch;\r
+ len ++;\r
+ break;\r
}\r
- \r
- write(_stdout, 1, &ch);\r
- ret[pos++] = ch;\r
- len ++;\r
} while(ch != '\n');\r
\r
- // Remove newline\r
- pos --;\r
- ret[pos] = '\0';\r
+ // Cap String\r
+ ret[len] = '\0';\r
+ printf("\n");\r
\r
// Return length\r
if(Length) *Length = len;\r
// === 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();
{
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
*/
char *GetUsername()
{
- char ret[BUFLEN];
+ char ret[BUFLEN] = {0};
int pos = 0;
char ch;
\r
// === CODE ===\r
/**\r
- * \fn FILE *freopen(FILE *fp, char *file, char *mode)\r
+ * \fn FILE *freopen(char *file, char *mode, FILE *fp)\r
*/\r
-EXPORT FILE *freopen(FILE *fp, char *file, char *mode)\r
+EXPORT FILE *freopen(const char *file, const char *mode, FILE *fp)\r
{\r
int openFlags = 0;\r
int i;\r
return fp;\r
}\r
/**\r
- \fn FILE *fopen(char *file, char *mode)\r
+ \fn FILE *fopen(const char *file, const char *mode)\r
\brief Opens a file and returns the pointer\r
\param file String - Filename to open\r
\param mode Mode to open in\r
*/\r
-EXPORT FILE *fopen(char *file, char *mode)\r
+EXPORT FILE *fopen(const char *file, const char *mode)\r
{\r
FILE *retFile;\r
\r
// Create Return Structure\r
retFile = get_file_struct();\r
\r
- return freopen(retFile, file, mode);\r
+ return freopen(file, mode, retFile);\r
}\r
\r
EXPORT void fclose(FILE *fp)\r
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
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)
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;
+}
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);
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);
\r
#include <stdlib.h>\r
#include <stdarg.h>\r
-
+\r
+// === Types ===
typedef struct sFILE FILE;
\r
+// === CONSTANTS ===\r
+#define EOF (-1)\r
+\r
+// --- Standard IO ---\r
extern int printf(const char *format, ...);\r
extern int vsprintf(char *buf, const char *format, va_list args);\r
-extern int sprintf(char *buf, const char *format, ...);
+extern int sprintf(char *buf, const char *format, ...);\r
\r
-extern FILE *fopen(char *file, char *mode);\r
-extern FILE *freopen(FILE *fp, char *file, char *mode);
+extern FILE *fopen(const char *file, const char *mode);\r
+extern FILE *freopen(const char *file, const char *mode, FILE *fp);\r
+extern FILE *fdopen(int fd, const char *modes);
extern void fclose(FILE *fp);\r
extern void fflush(FILE *fp);\r
extern long int ftell(FILE *fp);\r
/*\r
-AcessOS LibC\r
-\r
-stdlib.h\r
-*/\r
+ * AcessOS LibC\r
+ * stdlib.h\r
+ */\r
#ifndef __STDLIB_H\r
#define __STDLIB_H\r
\r
+#include <stddef.h>\r
#include <stdarg.h>\r
#include <sys/types.h>\r
\r
-#ifndef NULL\r
-# define NULL ((void*)0)\r
-#endif\r
-\r
#define EXIT_FAILURE 1\r
#define EXIT_SUCCESS 0\r
\r
-typedef unsigned int size_t;\r
-\r
// --- Spinlock Macros ---\r
#define DEFLOCK(_name) static int _spinlock_##_name=0;\r
//#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))\r
#define UNLOCK(_name) __asm__ __volatile__("lock andl $0, (%0)"::"D"(&_spinlock_##_name))\r
\r
// --- StdLib ---\r
+extern void _exit(int code); //NOTE: Also defined in acess/sys.h\r
extern int atoi(const char *ptr);\r
extern void exit(int status) __attribute__((noreturn));\r
extern void qsort(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *));\r
#ifndef __STRING_H
#define __STRING_H
-#include <stdlib.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);
+#include <stddef.h>
// 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