all: $(BIN)
clean:
- @$(RM) $(BIN) $(OBJ) $(DEPFILES)
+ @$(RM) $(BIN) $(BIN).dsm ../Map.$(ARCH).txt LineCounts.$(ARCH).txt $(OBJ) $(DEPFILES)
apidoc:
doxygen Doxyfile.api
return (gaPageTable[Addr >> 12] & ~0xFFF) | (Addr & 0xFFF);
}
+
+/**
+ * \fn int MM_IsUser(tVAddr Addr)
+ * \brief Checks if a page is user accessable
+ */
+int MM_IsUser(tVAddr Addr)
+{
+ if( !(gaPageDir[Addr >> 22] & 1) )
+ return 0;
+ if( !(gaPageTable[Addr >> 12] & 1) )
+ return 0;
+ if( !(gaPageTable[Addr >> 12] & PF_USER) )
+ return 0;
+ return 1;
+}
+
/**
* \fn void MM_SetCR3(tPAddr CR3)
* \brief Sets the current process space
/**
* \brief Checks is a memory range is user accessable
* \param VAddr Base address to check
- * \param Length Number of bytes to check
* \return 1 if the memory is all user-accessable, 0 otherwise
*/
-extern int MM_IsUser(tVAddr VAddr, int Length);
+extern int MM_IsUser(tVAddr VAddr);
/**
* \brief Set the access flags on a page
* \param VAddr Virtual address of the page
extern void *memcpyd(void *dest, const void *src, Uint count);
extern void *memset(void *dest, int val, Uint count);
extern void *memsetd(void *dest, Uint val, Uint count);
+/**
+ * \}
+ */
+/**
+ * \name Memory Validation
+ * \{
+ */
+extern int CheckString(char *String);
+extern int CheckMem(void *Mem, int Num);
/**
* \}
*/
extern void itoa(char *buf, Uint num, int base, int minLength, char pad);
extern int ReadUTF8(Uint8 *str, Uint32 *Val);
extern int WriteUTF8(Uint8 *str, Uint32 Val);
+extern int LookupString(char **Array, char *Needle);
/**
* \}
*/
DRV_IOCTL_LOOKUP
};
+#define DRV_IOCTLNAMES "type", "ident", "version", "lookup"
+
/**
* \enum eTplDrv_Type
* \brief Driver Types returned by DRV_IOCTL_TYPE
DRV_TYPE_NETWORK //!< Network Device
};
-// === FUNCTIONS ===
-/**
- * \fn int GetIOCtlId(int Class, char *Name)
- * \brief Transforms a symbolic name into an ID
- * \param Class ::eTplDrv_Type type to use
- * \param Name Symbolic name to resolve
- *
- * This function is designed to be used by device drivers to implement
- * ::eTplDrv_IOCtl.DRV_IOCTL_LOOKUP easily given that they conform to
- * the standard interfaces (::eTplDrv_Type except DRV_TYPE_MISC) and do
- * not add their own call numbers.
- */
-extern int GetIOCtlId(int Class, char *Name);
-
#endif
--- /dev/null
+/**\r
+ * \file tpl_drv_network.h\r
+ * \brief Network Interface Driver Interface Definitions\r
+*/\r
+#ifndef _TPL_NETWORK_H\r
+#define _TPL_NETWORK_H\r
+\r
+#include <tpl_drv_common.h>\r
+\r
+/**\r
+ * \enum eTplNetwork_IOCtl\r
+ * \brief Common Network IOCtl Calls\r
+ * \extends eTplDrv_IOCtl\r
+ */\r
+enum eTplNetwork_IOCtl {\r
+ /**\r
+ * ioctl(..., Uint8 *MAC[6])\r
+ * \brief Get the MAC address of the interface\r
+ */\r
+ NET_IOCTL_GETMAC = 4\r
+};\r
+\r
+#define DRV_NETWORK_IOCTLNAMES "get_mac_addr"\r
+\r
+#endif\r
#define VFS_PERM_DENY 0x80000000 // Inverts permissions
//! \}
-/**
- * \brief ACL Defintion Structure
- */
-typedef struct sVFS_ACL
-{
- struct {
- unsigned Group: 1; //!< Group (as opposed to user) flag
- unsigned ID: 31; //!< ID of Group/User (-1 for nobody/world)
- };
- struct {
- unsigned Inv: 1; //!< Invert Permissions
- unsigned Perms: 31; //!< Permission Flags
- };
-} tVFS_ACL;
-
/**
* \name VFS Node Flags
* \{
#define SEEK_CUR 0
#define SEEK_END -1
+// -- System Call Structures ---
+/**
+ * \brief ACL Defintion Structure
+ */
+typedef struct sVFS_ACL
+{
+ struct {
+ unsigned Group: 1; //!< Group (as opposed to user) flag
+ unsigned ID: 31; //!< ID of Group/User (-1 for nobody/world)
+ };
+ struct {
+ unsigned Inv: 1; //!< Invert Permissions
+ unsigned Perms: 31; //!< Permission Flags
+ };
+} tVFS_ACL;
+
+struct s_sysFInfo {
+ Uint uid, gid;
+ Uint flags;
+ Uint64 size;
+ Sint64 atime;
+ Sint64 mtime;
+ Sint64 ctime;
+ int numacls;
+ tVFS_ACL acls[];
+};
+
// === FUNCTIONS ===
extern int VFS_Init();
return giRandomState;
}
+/// \name Memory Validation
+/// \{
+/**
+ * \brief Checks if a string resides fully in valid memory
+ */
+int CheckString(char *String)
+{
+ // Check 1st page
+ if( MM_IsUser( (tVAddr)String ) )
+ {
+ // Traverse String
+ while( *String )
+ {
+ if( !MM_IsUser( (tVAddr)String ) )
+ return 0;
+ // Increment string pointer
+ String ++;
+ }
+ return 1;
+ }
+ else if( MM_GetPhysAddr( (tVAddr)String ) )
+ {
+ // Traverse String
+ while( *String )
+ {
+ if( !MM_GetPhysAddr( (tVAddr)String ) )
+ return 0;
+ // Increment string pointer
+ String ++;
+ }
+ return 1;
+ }
+ return 0;
+}
+
+/**
+ * \brief Check if a sized memory region is valid memory
+ */
+int CheckMem(void *Mem, int NumBytes)
+{
+ tVAddr addr = (tVAddr)Mem;
+
+ if( MM_IsUser( addr ) )
+ {
+ while( NumBytes-- )
+ {
+ if( !MM_IsUser( addr ) )
+ return 0;
+ addr ++;
+ }
+ return 1;
+ }
+ else if( MM_GetPhysAddr( addr ) )
+ {
+ while( NumBytes-- )
+ {
+ if( !MM_GetPhysAddr( addr ) )
+ return 0;
+ addr ++;
+ }
+ return 1;
+ }
+ return 0;
+}
+/// \}
+
+/**
+ * \brief Search a string array for \a Needle
+ * \note Helper function for eTplDrv_IOCtl::DRV_IOCTL_LOOKUP
+ */
+int LookupString(char **Array, char *Needle)
+{
+ int i;
+ for( i = 0; Array[i]; i++ )
+ {
+ if(strcmp(Array[i], Needle) == 0) return i;
+ }
+ return -1;
+}
+
+EXPORT(strdup);
+EXPORT(strcmp);
+EXPORT(strcpy);
+
EXPORT(timestamp);
EXPORT(ReadUTF8);
+EXPORT(CheckMem);
+EXPORT(CheckString);
#include <proc.h>
#include <errno.h>
+#define CHECK_NUM_NULLOK(v,size) do {\
+ if((v)&&!Syscall_Valid((size),(Uint)(v))){ret=-1;err=-EINVAL;break;}\
+ }while(0)
+#define CHECK_STR_NULLOK(v) do {\
+ if((v)&&!Syscall_ValidString((Uint)(v))){ret=-1;err=-EINVAL;break;}\
+ }while(0)
+#define CHECK_NUM_NONULL(v,size) do {\
+ if(!(v)||!Syscall_Valid((size),(Uint)(v))){ret=-1;err=-EINVAL;break;}\
+ }while(0)
+#define CHECK_STR_NONULL(v) do {\
+ if(!(v)||!Syscall_ValidString((Uint)(v))){ret=-1;err=-EINVAL;break;}\
+ }while(0)
+
// === IMPORTS ===
extern int Proc_Clone(Uint *Err, Uint Flags);
extern int Threads_WaitTID(int TID, int *status);
// -- Wait for a thread
case SYS_WAITTID:
+ // Sanity Check (Status can be NULL)
+ CHECK_NUM_NULLOK( Regs->Arg2, sizeof(int) );
+ // TID, *Status
ret = Threads_WaitTID(Regs->Arg1, (void*)Regs->Arg2);
break;
// -- Send Message
case SYS_SENDMSG:
+ CHECK_NUM_NONULL(Regs->Arg3, Regs->Arg2);
+ // Destination, Size, *Data
ret = Proc_SendMessage(&err, Regs->Arg1, Regs->Arg2, (void*)Regs->Arg3);
break;
// -- Check for messages
case SYS_GETMSG:
+ CHECK_NUM_NULLOK(Regs->Arg1, sizeof(Uint));
+ //NOTE: Uncertain due to length being unknown
+ // (Proc_GetMessage should check itself)
+ CHECK_NUM_NULLOK(Regs->Arg2, sizeof(Uint)*4);
+ // *Source, *Data
ret = Proc_GetMessage(&err, (Uint*)Regs->Arg1, (void*)Regs->Arg2);
break;
// -- Set the thread's name
case SYS_SETNAME:
- // Sanity Check
- if(!Regs->Arg1) { ret = -1; err = -EINVAL; break; }
- Threads_SetName( (void*)Regs->Arg1 );
+ CHECK_STR_NONULL(Regs->Arg1);
+ Threads_SetName( (char*)Regs->Arg1 );
break;
// ---
// Binary Control
// ---
case SYS_EXECVE:
- if( !Syscall_ValidString(Regs->Arg1) ) {
- err = -EINVAL;
- ret = -1;
- break;
+ CHECK_STR_NONULL(Regs->Arg1);
+ {
+ int i;
+ char **tmp = (char**)Regs->Arg2;
+ // Check ArgV (traverse array checking all string pointers)
+ CHECK_NUM_NONULL( tmp, sizeof(char**) );
+ for(i=0;tmp[i];i++) {
+ CHECK_NUM_NULLOK( &tmp[i], sizeof(char*) );
+ CHECK_STR_NONULL( tmp[i] );
+ }
+ // Check EnvP also
+ // - EnvP can be NULL
+ if( Regs->Arg3 )
+ {
+ tmp = (char**)Regs->Arg3;
+ for(i=0;tmp[i];i++) {
+ CHECK_NUM_NULLOK( &tmp[i], sizeof(char*) );
+ CHECK_STR_NONULL( tmp[i] );
+ }
+ }
}
+ // Path, **Argv, **Envp
ret = Proc_Execve((char*)Regs->Arg1, (char**)Regs->Arg2, (char**)Regs->Arg3);
break;
case SYS_LOADBIN:
ret = -1;
break;
}
+ // Path, *Entrypoint
ret = Binary_Load((char*)Regs->Arg1, (Uint*)Regs->Arg2);
break;
break;
case SYS_SEEK:
- ret = VFS_Seek( Regs->Arg1, Regs->Arg2, Regs->Arg3);
+ ret = VFS_Seek( Regs->Arg1, Regs->Arg2, Regs->Arg3 );
break;
case SYS_TELL:
break;
case SYS_WRITE:
- #if BITS < 64
- ret = VFS_Write( Regs->Arg1, Regs->Arg2|((Uint64)Regs->Arg3<<32), (void*)Regs->Arg4 );
- #else
+ CHECK_NUM_NONULL( Regs->Arg3, Regs->Arg2 );
ret = VFS_Write( Regs->Arg1, Regs->Arg2, (void*)Regs->Arg3 );
- #endif
break;
case SYS_READ:
- #if BITS < 64
- ret = VFS_Read( Regs->Arg1, Regs->Arg2|((Uint64)Regs->Arg3<<32), (void*)Regs->Arg4 );
- #else
+ CHECK_NUM_NONULL( Regs->Arg3, Regs->Arg2 );
ret = VFS_Read( Regs->Arg1, Regs->Arg2, (void*)Regs->Arg3 );
- #endif
break;
case SYS_FINFO:
+ CHECK_NUM_NONULL( Regs->Arg2, sizeof(struct s_sysFInfo) + Regs->Arg3*sizeof(tVFS_ACL) );
+ // FP, Dest, MaxACLs
ret = VFS_FInfo( Regs->Arg1, (void*)Regs->Arg2, Regs->Arg3 );
break;
// Get ACL Value
case SYS_GETACL:
- if( !Syscall_Valid(8, Regs->Arg1) ) {
+ if( !Syscall_Valid(sizeof(tVFS_ACL), Regs->Arg1) ) {
err = -EINVAL;
ret = -1;
break;
// Read Directory
case SYS_READDIR:
- if( !Syscall_ValidString(Regs->Arg2) ) {
+ if( !Syscall_Valid(8, Regs->Arg2) ) {
err = -EINVAL;
ret = -1;
break;
// IO Control
case SYS_IOCTL:
+ // All sanity checking should be done by the driver
ret = VFS_IOCtl( Regs->Arg1, Regs->Arg2, (void*)Regs->Arg3 );
break;
break;
// -- Debug
+ #if DEBUG_BUILD
case SYS_DEBUG:
Log((char*)Regs->Arg1,
Regs->Arg2, Regs->Arg3, Regs->Arg4, Regs->Arg5, Regs->Arg6);
break;
+ #endif
// -- Default (Return Error)
default:
#endif
Regs->Error = err;
#if DEBUG
- LOG("SyscallHandler: err = %i", err);
+ LOG("err = %i", err);
LEAVE('x', ret);
#endif
}
*/
int Syscall_ValidString(Uint Addr)
{
- // Check 1st page
- if(!MM_GetPhysAddr(Addr)) return 0;
+ // Check if the memory is user memory
+ if(!MM_IsUser(Addr)) return 0;
- // Traverse String
- while(*(char*)Addr)
- {
- if(!MM_GetPhysAddr(Addr)) return 0;
- // Increment string pointer
- Addr ++;
- }
-
- return 1;
+ return CheckString( (char*)Addr );
}
/**
*/
int Syscall_Valid(int Size, Uint Addr)
{
- while(Size--)
- {
- if(!MM_GetPhysAddr(Addr)) return 0;
- Addr ++;
- }
- return 1;
+ if(!MM_IsUser(Addr)) return 0;
+
+ return CheckMem( (void*)Addr, Size );
}
return h->Node->IOCtl(h->Node, ID, Buffer);
}
-// -- System Call Structures ---
-struct s_sysFInfo {
- Uint uid, gid;
- Uint flags;
- Uint64 size;
- Sint64 atime;
- Sint64 mtime;
- Sint64 ctime;
- int numacls;
- tVFS_ACL acls[];
-};
-
/**
* \fn int VFS_FInfo(int FD, struct s_sysFInfo *Dest, int MaxACLs)
* \brief Retrieve file information
@$(MAKE) all --no-print-directory -C Usermode/Applications/cat_src
@echo === ls
@$(MAKE) all --no-print-directory -C Usermode/Applications/ls_src
+ @echo === mount
+ @$(MAKE) all --no-print-directory -C Usermode/Applications/mount_src
clean:
- make clean --no-print-directory -C Kernel/
- make clean --no-print-directory -C Usermode/Libraries/ld-acess.so_src
- make clean --no-print-directory -C Usermode/Libraries/libacess.so_src
- make clean --no-print-directory -C Usermode/Libraries/libc.so_src
- make clean --no-print-directory -C Usermode/Libraries/libgcc.so_src
- make clean --no-print-directory -C Usermode/Applications/init_src
- make clean --no-print-directory -C Usermode/Applications/login_src
- make clean --no-print-directory -C Usermode/Applications/CLIShell_src
- make clean --no-print-directory -C Usermode/Applications/cat_src
- make clean --no-print-directory -C Usermode/Applications/ls_src
+ @make clean --no-print-directory -C Kernel/
+ @make clean --no-print-directory -C Usermode/Libraries/ld-acess.so_src
+ @make clean --no-print-directory -C Usermode/Libraries/libacess.so_src
+ @make clean --no-print-directory -C Usermode/Libraries/libc.so_src
+ @make clean --no-print-directory -C Usermode/Libraries/libgcc.so_src
+ @make clean --no-print-directory -C Usermode/Applications/init_src
+ @make clean --no-print-directory -C Usermode/Applications/login_src
+ @make clean --no-print-directory -C Usermode/Applications/CLIShell_src
+ @make clean --no-print-directory -C Usermode/Applications/cat_src
+ @make clean --no-print-directory -C Usermode/Applications/ls_src
+ @make clean --no-print-directory -C Usermode/Applications/mount_src
*/
void ICMP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffer)
{
- tICMPHeader *hdr = Buffer;
+ //tICMPHeader *hdr = Buffer;
}
*/
struct sAdapter {
struct sAdapter *Next;
- char *Device;
+
int DeviceFD;
+ int NRef;
tMacAddr MacAddr;
-
- tInterface *Interfaces;
+ char Device[];
};
static const tMacAddr cMAC_BROADCAST = {{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}};
#include "link.h"
#include "ipv4.h"
+// === IMPORTS ===
+extern tInterface *gIP_Interfaces;
+
// === PROTOTYPES ===
int IPv4_Initialise();
void IPv4_int_GetPacket(tAdapter *Interface, tMacAddr From, int Length, void *Buffer);
{
tIPv4Header *hdr = Buffer;
tInterface *iface;
- char *data;
+ Uint8 *data;
int dataLength;
if(Length < sizeof(tIPv4Header)) return;
tInterface *iface = NULL;
Uint32 netmask;
- for( iface = Adapter->Interfaces; iface; iface = iface->Next)
+ for( iface = gIP_Interfaces; iface; iface = iface->Next)
{
+ if( iface->Adapter != Adapter ) continue;
if( iface->Type != 4 ) continue;
if( IP4_EQU(Address, iface->IP4.Address) )
return iface;
#include "ipv6.h"
// === IMPORTS ===
+extern tInterface *gIP_Interfaces;
extern Uint32 IPv4_Netmask(int FixedBits);
// === PROTOTYPES ===
tInterface *iface = NULL;
Uint32 netmask;
- for( iface = Adapter->Interfaces; iface; iface = iface->Next)
+ for( iface = gIP_Interfaces; iface; iface = iface->Next)
{
+ // Check for this adapter
+ if( iface->Adapter != Adapter ) continue;
+
// Skip non-IPv6 Interfaces
if( iface->Type != 6 ) continue;
/**
* \fn void Link_RegisterType(Uint16 Type, tPacketCallback Callback)
* \brief Registers a callback for a specific packet type
+ *
+ * \todo Make thread safe (place a mutex on the list)
*/
void Link_RegisterType(Uint16 Type, tPacketCallback Callback)
{
if(gaRegisteredTypes[i].Callback == NULL) break;
}
- if(i + 1 == 0)
+ if(i == -1)
{
tmp = realloc(gaRegisteredTypes, (giRegisteredTypes+1)*sizeof(*gaRegisteredTypes));
if(!tmp) Panic("[NET ] Out of heap space!");
tEthernetHeader *hdr = (void*)buf;
int ret, i;
- // Wait for a packet
+ // Wait for a packet (Read on a network device is blocking)
ret = VFS_Read(Adapter->DeviceFD, MAX_PACKET_SIZE, buf);
if(ret == -1) break;
if(gaRegisteredTypes[i].Type == hdr->Type) continue;
}
// No? Ignore it
- if( i + 1 == 0 ) continue;
+ if( i == -1 ) continue;
// Call the callback
gaRegisteredTypes[i].Callback(
hdr->Data
);
}
+
+ Log("[NET ] Watcher terminated (file closed)");
}
* Acess2 IP Stack
* - Address Resolution Protocol
*/
+#define DEBUG 0
+#define VERSION ((0<<8)|10)
#include "ipstack.h"
#include <modules.h>
#include <fs_devfs.h>
+#include <tpl_drv_common.h>
+#include <tpl_drv_network.h>
// === IMPORTS ===
int ARP_Initialise();
int IPStack_Install(char **Arguments);
char *IPStack_ReadDir(tVFS_Node *Node, int Pos);
tVFS_Node *IPStack_FindDir(tVFS_Node *Node, char *Name);
+ int IPStack_IOCtl(tVFS_Node *Node, int ID, void *Data);
+ int IPStack_AddInterface(char *Device);
+tAdapter *IPStack_GetAdapter(char *Path);
// === GLOBALS ===
-MODULE_DEFINE(0, 0x000A, IPStack, IPStack_Install, NULL);
+MODULE_DEFINE(0, VERSION, IPStack, IPStack_Install, NULL, NULL);
tDevFS_Driver gIP_DriverInfo = {
NULL, "ip",
{
+ .Size = 0, // Number of interfaces
.NumACLs = 1,
.ACLs = &gVFS_ACL_EveryoneRX,
.Flags = VFS_FFLAG_DIRECTORY,
.FindDir = IPStack_FindDir
}
};
- int giIP_NumInterfaces;
+ int glIP_Interfaces = 0;
tInterface *gIP_Interfaces = NULL;
+tInterface *gIP_Interfaces_Last = NULL;
+ int glIP_Adapters = 0;
+tAdapter *gIP_Adapters = NULL;
// === CODE ===
/**
*/
tVFS_Node *IPStack_FindDir(tVFS_Node *Node, char *Name)
{
- return NULL;
+ int i;
+ tInterface *iface;
+
+ if(Name[0] != 'i' || Name[1] != 'p') return NULL;
+ if(Name[2] < '0' || Name[2] > '9') return NULL;
+
+ if(Name[3] == '\0') {
+ i = Name[2] - '0';
+ for( iface = gIP_Interfaces; iface && i--; iface = iface->Next ) ;
+ if(!iface) return NULL;
+ return &iface->Node;
+ }
+
+ if(Name[3] < '0' || Name[3] > '9') return NULL;
+
+ i = (Name[2] - '0')*10;
+ i += Name[3] - '0';
+
+ for( iface = gIP_Interfaces; iface && i--; iface = iface->Next ) ;
+ if(!iface) return NULL;
+ return &iface->Node;
+}
+
+static const char *casIOCtls[] = { DRV_IOCTLNAMES, "add_interface", NULL };
+/**
+ * \brief Handles IOCtls for the IPStack root
+ */
+int IPStack_IOCtl(tVFS_Node *Node, int ID, void *Data)
+{
+ switch(ID)
+ {
+ // --- Standard IOCtls (0-3) ---
+ case DRV_IOCTL_TYPE:
+ return DRV_TYPE_MISC;
+
+ case DRV_IOCTL_IDENT:
+ if( !CheckMem( Data, 4 ) ) return -1;
+ memcpy(Data, "IP\0\0", 4);
+ return 1;
+
+ case DRV_IOCTL_VERSION:
+ return VERSION;
+
+ case DRV_IOCTL_LOOKUP:
+ if( !CheckString( Data ) ) return -1;
+ return LookupString( (char**)casIOCtls, (char*)Data );
+
+ // --- Non-Standard IOCtls ---
+ /*
+ * add_interface
+ * - Adds a new IP interface and binds it to a device
+ */
+ case 4:
+ if( !CheckString( Data ) ) return -1;
+ return IPStack_AddInterface(Data);
+ }
+ return 0;
+}
+
+// --- Internal ---
+/**
+ * \fn int IPStack_AddInterface(char *Device)
+ * \brief Adds an interface to the list
+ */
+int IPStack_AddInterface(char *Device)
+{
+ tInterface *iface;
+
+ iface = malloc(sizeof(tInterface));
+ if(!iface) return -2; // Return ERR_MYBAD
+
+ iface->Next = NULL;
+ iface->Type = 0; // Unset type
+
+ // Create Node
+ iface->Node.Flags = VFS_FFLAG_DIRECTORY;
+ iface->Node.Size = 0;
+ iface->Node.NumACLs = 1;
+ iface->Node.ACLs = &gVFS_ACL_EveryoneRX;
+ iface->Node.ReadDir = NULL;
+ iface->Node.FindDir = NULL;
+
+ // Get adapter handle
+ iface->Adapter = IPStack_GetAdapter(Device);
+ if( !iface->Adapter ) {
+ free( iface );
+ return -1; // Return ERR_YOUFAIL
+ }
+
+ // Append to list
+ LOCK( &glIP_Interfaces );
+ if( gIP_Interfaces ) {
+ gIP_Interfaces_Last->Next = iface;
+ gIP_Interfaces_Last = iface;
+ }
+ else {
+ gIP_Interfaces = iface;
+ gIP_Interfaces_Last = iface;
+ }
+ RELEASE( &glIP_Interfaces );
+
+ // Success!
+ return 1;
+}
+
+/**
+ * \fn tAdapter *IPStack_GetAdapter(char *Path)
+ * \brief Gets/opens an adapter given the path
+ */
+tAdapter *IPStack_GetAdapter(char *Path)
+{
+ tAdapter *dev;
+
+ LOCK( &glIP_Adapters );
+
+ // Check if this adapter is already open
+ for( dev = gIP_Adapters; dev; dev = dev->Next )
+ {
+ if( strcmp(dev->Device, Path) == 0 ) {
+ dev->NRef ++;
+ RELEASE( &glIP_Adapters );
+ return dev;
+ }
+ }
+
+ // Ok, so let's open it
+ dev = malloc( sizeof(tAdapter) + strlen(Path) + 1 );
+ if(!dev) {
+ RELEASE( &glIP_Adapters );
+ return NULL;
+ }
+
+ // Fill Structure
+ strcpy( dev->Device, Path );
+ dev->NRef = 1;
+
+ // Open Device
+ dev->DeviceFD = VFS_Open( dev->Device, VFS_OPENFLAG_READ|VFS_OPENFLAG_WRITE );
+ if( dev->DeviceFD == -1 ) {
+ free( dev );
+ RELEASE( &glIP_Adapters );
+ return NULL;
+ }
+
+ // Check that it is a network interface
+ if( VFS_IOCtl(dev->DeviceFD, 0, NULL) != DRV_TYPE_NETWORK ) {
+ Warning("IPStack_GetAdapter: '%s' is not a network interface", dev->Device);
+ VFS_Close( dev->DeviceFD );
+ free( dev );
+ RELEASE( &glIP_Adapters );
+ return NULL;
+ }
+
+ // Get MAC Address
+ VFS_IOCtl(dev->DeviceFD, NET_IOCTL_GETMAC, &dev->MacAddr);
+
+ // Add to list
+ dev->Next = gIP_Adapters;
+ gIP_Adapters = dev;
+
+ RELEASE( &glIP_Adapters );
+ return dev;
}
* See: ~/Sources/bochs/bochs.../iodev/ne2k.cc
*/
#define DEBUG 1
+#define VERSION ((0<<8)|50)
#include <common.h>
#include <modules.h>
#include <fs_devfs.h>
int Ne2k_Install(char **Arguments);
char *Ne2k_ReadDir(tVFS_Node *Node, int Pos);
tVFS_Node *Ne2k_FindDir(tVFS_Node *Node, char *Name);
+ int Ne2k_IOCtl(tVFS_Node *Node, int ID, void *Data);
Uint64 Ne2k_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
Uint8 Ne2k_int_GetWritePage(tCard *Card, Uint16 Length);
void Ne2k_IRQHandler(int IntNum);
// === GLOBALS ===
-MODULE_DEFINE(0, 0x0032, Ne2k, Ne2k_Install, NULL, NULL);
+MODULE_DEFINE(0, VERSION, Ne2k, Ne2k_Install, NULL, NULL);
tDevFS_Driver gNe2k_DriverInfo = {
NULL, "ne2k",
{
gpNe2k_Cards[ k ].Node.NumACLs = 0; // Root Only
gpNe2k_Cards[ k ].Node.CTime = now();
gpNe2k_Cards[ k ].Node.Write = Ne2k_Write;
+ gpNe2k_Cards[ k ].Node.IOCtl = Ne2k_IOCtl;
}
}
return &gpNe2k_Cards[ Name[0]-'0' ].Node;
}
+static const char *casIOCtls[] = { DRV_IOCTLNAMES, DRV_NETWORK_IOCTLNAMES, NULL };
+/**
+ * \fn int Ne2k_IOCtl(tVFS_Node *Node, int ID, void *Data)
+ * \brief IOCtl calls for a network device
+ */
+int Ne2k_IOCtl(tVFS_Node *Node, int ID, void *Data)
+{
+ switch( ID )
+ {
+ case DRV_IOCTL_TYPE: return DRV_TYPE_NETWORK;
+ case DRV_IOCTL_IDENT:
+ if(!CheckMem(Data, 4)) return -1;
+ memcpy(Data, "NE2K", 4);
+ return 1;
+ case DRV_IOCTL_VERSION: return VERSION;
+ case DRV_IOCTL_LOOKUP:
+ if(!CheckString(Data)) return -1;
+ return LookupString( casIOCtls, Data );
+ }
+
+ // If this is the root, return
+ if( Node == &gNe2k_DriverInfo.Node ) return 0;
+
+ // Device specific settings
+ switch( ID )
+ {
+ case NET_IOCTL_GETMAC:
+ if(!CheckMem(Data, 6)) return -1;
+ memcpy( Data, ((tCard*)Node->ImplPtr)->MacAddr, 6 );
+ return 1;
+ }
+ return 0;
+}
+
/**
* \fn Uint64 Ne2k_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
+ * \brief Send a packet from the network card
*/
Uint64 Ne2k_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
{
--- /dev/null
+/*
+ * Acess 2 USB Stack
+ * USB Packet Control
+ */
+#define DEBUG 1
+#include <common.h>
+#include <vfs.h>
+#include <drv_pci.h>
+#include "usb.h"
+
+
+// === CODE ===
+void USB_MakeToken(void *Buf, int PID, int Addr, int EndP)
+{
+ Uint8 *tok = Buf;
+ int crc = 0; //USB_TokenCRC();
+
+ tok[0] = PID;
+ tok[1] = Addr | ((EndP&1)<<7);
+ tok[2] = (EndP >> 1) | crc;
+}
all: $(BIN)\r
\r
clean:\r
- $(RM) $(COBJ) $(BIN)\r
+ $(RM) $(COBJ) $(BIN) $(BIN).dsm Map.txt\r
\r
$(BIN): $(COBJ)\r
@echo --- $(LD) -o $@\r
@echo --- $(LD) -o $@\r
@$(LD) $(LDFLAGS) -o $@ $(COBJ) -Map Map.txt\r
objdump -d $(BIN) > $(BIN).dsm\r
- cp $(BIN) $(DISTROOT)/Bin/\r
+ cp $(BIN) $(DISTROOT)/Bin/
\r
clean:\r
- $(RM) $(COBJ) $(BIN)\r
+ $(RM) $(COBJ) $(BIN) $(BIN).dsm Map.txt
\r
$(COBJ): %.o: %.c\r
@echo --- GCC -o $@
all: $(BIN)
clean:
- $(RM) $(BIN) $(OBJ)
+ $(RM) $(BIN) $(OBJ) login.dsm
$(BIN): $(OBJ)
@echo --- $(LD) -o $@
cp $(BIN) $(DISTROOT)/Bin/\r
\r
clean:\r
- $(RM) $(COBJ) $(BIN)\r
+ $(RM) $(COBJ) $(BIN) $(BIN).dsm Map.txt
\r
$(COBJ): %.o: %.c\r
@echo --- GCC -o $@
cp $(BIN) $(DISTROOT)/Bin/\r
\r
clean:\r
- $(RM) $(COBJ) $(BIN)\r
+ $(RM) $(COBJ) $(BIN) Map.txt $(BIN).dsm
\r
$(COBJ): %.o: %.c\r
@echo --- GCC -o $@
all: $(BIN)\r
\r
clean:\r
- $(RM) $(BIN) $(AOBJ) $(COBJ)\r
+ $(RM) $(BIN) $(AOBJ) $(COBJ) ld-acess.dmp ld-acess.dsm link.txt map.txt\r
\r
$(BIN): $(AOBJ) $(COBJ)\r
@echo --- $(LD) -shared -o $@\r
all: $(BIN) $(OBJ_LIBC)\r
\r
clean:\r
- $(RM) $(BIN) $(OBJ_LIBC)\r
+ $(RM) $(BIN) ../libc.so $(OBJ_LIBC) libc.so.1.dsm libc.so.1.dmp map.txt\r
\r
# Core C Library\r
$(BIN): $(OBJ_LIBC)\r
all: $(BIN)
clean:
- $(RM) $(BIN) $(OBJS)
+ $(RM) $(BIN) $(OBJS) libgcc.so.dsm
$(BIN): $(OBJS)
@echo -- ld -o $@