From f035491c949cb86d92a93fc3d9d033538704256b Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sat, 21 Nov 2009 00:06:55 +0800 Subject: [PATCH] Cleanup and Bugfixing - Created a _very_ basic `ifconfig` app to test the IPStack module - Fixed a bug in MM_NewWorkerStack that caused it to always fail - Added the LEAVE_RET macro to simplify debugging - Moved BochsGA driver to module tree - More work on the IPStack - Fixed compile errors in NE2000 driver - and did some work on the makefiles --- Kernel/arch/x86/mm_virt.c | 3 +- Kernel/binary.c | 2 +- Kernel/drv/vterm.c | 4 +- Kernel/include/common.h | 3 + Makefile | 14 +- Modules/BochsGA/Makefile | 7 + Modules/BochsGA/bochsvbe.c | 469 ++++++++++++++++++++ Modules/IPStack/link.h | 1 + Modules/IPStack/main.c | 285 ++++++++---- Modules/Makefile.tpl | 5 +- Modules/NE2000/ne2000.c | 44 +- Usermode/Applications/ifconfig_src/Makefile | 27 ++ Usermode/Applications/ifconfig_src/main.c | 171 +++++++ 13 files changed, 933 insertions(+), 102 deletions(-) create mode 100644 Modules/BochsGA/Makefile create mode 100644 Modules/BochsGA/bochsvbe.c create mode 100644 Usermode/Applications/ifconfig_src/Makefile create mode 100644 Usermode/Applications/ifconfig_src/main.c diff --git a/Kernel/arch/x86/mm_virt.c b/Kernel/arch/x86/mm_virt.c index 44e18651..9892998d 100644 --- a/Kernel/arch/x86/mm_virt.c +++ b/Kernel/arch/x86/mm_virt.c @@ -63,7 +63,7 @@ tPAddr *gaTmpDir = (void*)TMP_DIR_ADDR; tPAddr *gTmpCR3 = (void*)TMP_CR3_ADDR; int gilTempMappings = 0; int gilTempFractal = 0; -Uint32 gWorkerStacks[NUM_WORKER_STACKS/32]; +Uint32 gWorkerStacks[(NUM_WORKER_STACKS+31)/32]; int giLastUsedWorker = 0; // === CODE === @@ -615,6 +615,7 @@ tVAddr MM_NewWorkerStack() if( gWorkerStacks[base/32] & (1 << base) ) { continue; } + break; } if(base >= NUM_WORKER_STACKS) { Warning("Uh-oh! Out of worker stacks"); diff --git a/Kernel/binary.c b/Kernel/binary.c index 43d8cb35..e96da76d 100644 --- a/Kernel/binary.c +++ b/Kernel/binary.c @@ -12,7 +12,7 @@ //! \todo Move 0xBC000000 to mm_virt.h #define BIN_HIGHEST (0xBC000000-BIN_GRANUALITY) // Just below the kernel #define KLIB_LOWEST MM_MODULE_MIN -#define KLIB_GRANUALITY 0x8000 // 32KiB +#define KLIB_GRANUALITY 0x10000 // 32KiB #define KLIB_HIGHEST (MM_MODULE_MAX-KLIB_GRANUALITY) // === TYPES === diff --git a/Kernel/drv/vterm.c b/Kernel/drv/vterm.c index 96f02ed5..d33fad98 100644 --- a/Kernel/drv/vterm.c +++ b/Kernel/drv/vterm.c @@ -16,8 +16,8 @@ #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 "BochsGA" +#define DEFAULT_OUTPUT "VGA" +//#define DEFAULT_OUTPUT "BochsGA" #define DEFAULT_INPUT "PS2Keyboard" #define DEFAULT_WIDTH 80 #define DEFAULT_HEIGHT 25 diff --git a/Kernel/include/common.h b/Kernel/include/common.h index 7638b481..0ff9c7f1 100644 --- a/Kernel/include/common.h +++ b/Kernel/include/common.h @@ -102,10 +102,13 @@ extern void Debug_HexDump(char *Header, void *Data, Uint Length); # define ENTER(_types...) Debug_Enter((char*)__func__, _types) # define LOG(_fmt...) Debug_Log((char*)__func__, _fmt) # define LEAVE(_t...) Debug_Leave((char*)__func__, _t) +# define LEAVE_RET(_t,_v...) do{LEAVE(_t,_v);return _v;}while(0) +//# define LEAVE_RET(_t) do{LEAVE(_t);return;} #else # define ENTER(...) # define LOG(...) # define LEAVE(...) +# define LEAVE_RET(_t,_v...) return (_v) #endif /** * \} diff --git a/Makefile b/Makefile index 88b8377d..90ed23c7 100644 --- a/Makefile +++ b/Makefile @@ -4,24 +4,24 @@ .PHONY: all clean -MODULES = IPStack +MODULES = FS_Ext2 FDD BochsGA IPStack NE2000 USRLIBS = ld-acess.so libacess.so libgcc.so libc.so -USRAPPS = init login CLIShell cat ls mount +USRAPPS = init login CLIShell cat ls mount ifconfig all: @for mod in $(MODULES); do \ - (echo === $$mod && $(MAKE) all --no-print-directory -C Modules/$$mod) \ + (echo === Module: $$mod && $(MAKE) all --no-print-directory -C Modules/$$mod) \ done @echo === Kernel @$(MAKE) all --no-print-directory -C Kernel @for lib in $(USRLIBS); do \ - (echo === $$lib && $(MAKE) all --no-print-directory -C Usermode/Libraries/`echo $$lib`_src) \ + (echo === User Library: $$lib && $(MAKE) all --no-print-directory -C Usermode/Libraries/`echo $$lib`_src) \ done @for app in $(USRAPPS); do \ - (echo === $$app && $(MAKE) all --no-print-directory -C Usermode/Applications/`echo $$app`_src) \ + (echo === User Application: $$app && $(MAKE) all --no-print-directory -C Usermode/Applications/`echo $$app`_src) \ done # @echo === ld-acess.so @@ -46,6 +46,10 @@ all: # @$(MAKE) all --no-print-directory -C Usermode/Applications/mount_src clean: + @for mod in $(MODULES); do \ + ($(MAKE) clean --no-print-directory -C Modules/$$mod) \ + done + @make clean --no-print-directory -C Kernel/ @for lib in $(USRLIBS); do \ diff --git a/Modules/BochsGA/Makefile b/Modules/BochsGA/Makefile new file mode 100644 index 00000000..2df219af --- /dev/null +++ b/Modules/BochsGA/Makefile @@ -0,0 +1,7 @@ +# +# + +OBJ = bochsvbe.o +NAME = BochsGA + +-include ../Makefile.tpl diff --git a/Modules/BochsGA/bochsvbe.c b/Modules/BochsGA/bochsvbe.c new file mode 100644 index 00000000..a833503f --- /dev/null +++ b/Modules/BochsGA/bochsvbe.c @@ -0,0 +1,469 @@ +/** + * \file drv_bochsvbe.c + * \brief BGA (Bochs Graphic Adapter) Driver + * \note for Acess2 + * \warning This driver does NOT support the Bochs PCI VGA driver +*/ +#define DEBUG 0 +#include +#include +#include +#include +#include +#include +#include + +//#define INT static +#define INT + +// === TYPEDEFS === +typedef struct { + Uint16 width; + Uint16 height; + Uint16 bpp; + Uint16 flags; + Uint32 fbSize; +} t_bga_mode; + +// === CONSTANTS === +enum eMode_Flags { + MODEFLAG_TEXT = 1 +}; +#define BGA_LFB_MAXSIZE (1024*768*4) +#define VBE_DISPI_BANK_ADDRESS 0xA0000 +#define VBE_DISPI_LFB_PHYSICAL_ADDRESS 0xE0000000 +#define VBE_DISPI_IOPORT_INDEX 0x01CE +#define VBE_DISPI_IOPORT_DATA 0x01CF +#define VBE_DISPI_DISABLED 0x00 +#define VBE_DISPI_ENABLED 0x01 +#define VBE_DISPI_LFB_ENABLED 0x40 +#define VBE_DISPI_NOCLEARMEM 0x80 +enum { + VBE_DISPI_INDEX_ID, + VBE_DISPI_INDEX_XRES, + VBE_DISPI_INDEX_YRES, + VBE_DISPI_INDEX_BPP, + VBE_DISPI_INDEX_ENABLE, + VBE_DISPI_INDEX_BANK, + VBE_DISPI_INDEX_VIRT_WIDTH, + VBE_DISPI_INDEX_VIRT_HEIGHT, + VBE_DISPI_INDEX_X_OFFSET, + VBE_DISPI_INDEX_Y_OFFSET +}; + + +// === PROTOTYPES === +// Driver + int BGA_Install(char **Arguments); +void BGA_Uninstall(); +// Internal +void BGA_int_WriteRegister(Uint16 reg, Uint16 value); +Uint16 BGA_int_ReadRegister(Uint16 reg); +void BGA_int_SetBank(Uint16 bank); +void BGA_int_SetMode(Uint16 width, Uint16 height); + int BGA_int_UpdateMode(int id); + int BGA_int_FindMode(tVideo_IOCtl_Mode *info); + int BGA_int_ModeInfo(tVideo_IOCtl_Mode *info); + int BGA_int_MapFB(void *Dest); +// Filesystem +Uint64 BGA_Read(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer); +Uint64 BGA_Write(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer); + int BGA_Ioctl(tVFS_Node *node, int id, void *data); + +// === GLOBALS === +MODULE_DEFINE(0, 0x0032, BochsGA, BGA_Install, NULL, NULL); +tDevFS_Driver gBGA_DriverStruct = { + NULL, "BochsGA", + { + .Read = BGA_Read, + .Write = BGA_Write, + .IOCtl = BGA_Ioctl + } +}; + int giBGA_CurrentMode = -1; +tVideo_IOCtl_Pos gBGA_CursorPos = {-1,-1}; + int giBGA_DriverId = -1; +Uint *gBGA_Framebuffer; +t_bga_mode gBGA_Modes[] = { + {}, + { 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}, + {800,600,32, 0, 800*600*4}, +}; +#define BGA_MODE_COUNT (sizeof(gBGA_Modes)/sizeof(gBGA_Modes[0])) + +// === CODE === +/** + * \fn int BGA_Install(char **Arguments) + */ +int BGA_Install(char **Arguments) +{ + int bga_version = 0; + + // Check BGA Version + bga_version = BGA_int_ReadRegister(VBE_DISPI_INDEX_ID); + // NOTE: This driver was written for 0xB0C4, but they seem to be backwards compatable + if(bga_version < 0xB0C4 || bga_version > 0xB0C5) { + Warning("[BGA ] Bochs Adapter Version is not 0xB0C4 or 0xB0C5, instead 0x%x", bga_version); + return 0; + } + + // Install Device + giBGA_DriverId = DevFS_AddDevice( &gBGA_DriverStruct ); + if(giBGA_DriverId == -1) { + Warning("[BGA ] Unable to register with DevFS, maybe already loaded?"); + return 0; + } + + // Map Framebuffer to hardware address + gBGA_Framebuffer = (void *) MM_MapHWPage(VBE_DISPI_LFB_PHYSICAL_ADDRESS, 768); // 768 pages (3Mb) + + return 1; +} + +/** + * \fn void BGA_Uninstall() + */ +void BGA_Uninstall() +{ + //DevFS_DelDevice( giBGA_DriverId ); + MM_UnmapHWPage( VBE_DISPI_LFB_PHYSICAL_ADDRESS, 768 ); +} + +/** + * \fn Uint64 BGA_Read(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer) + * \brief Read from the framebuffer + */ +Uint64 BGA_Read(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer) +{ + // Check Mode + if(giBGA_CurrentMode == -1) return -1; + + // Check Offset and Length against Framebuffer Size + if(off+len > gBGA_Modes[giBGA_CurrentMode].fbSize) + return -1; + + // Copy from Framebuffer + memcpy(buffer, (void*)((Uint)gBGA_Framebuffer + (Uint)off), len); + return len; +} + +/** + * \fn Uint64 BGA_Write(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer) + * \brief Write to the framebuffer + */ +Uint64 BGA_Write(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer) +{ + ENTER("xoff xlen", off, len); + + // Check Mode + if(giBGA_CurrentMode == -1) { + LEAVE('i', -1); + return -1; + } + + // Check Input against Frambuffer Size + if(off+len > gBGA_Modes[giBGA_CurrentMode].fbSize) { + LEAVE('i', -1); + return -1; + } + + // Text Mode + if( gBGA_Modes[giBGA_CurrentMode].flags & MODEFLAG_TEXT ) + { + tVT_Char *chars = buffer; + int pitch = gBGA_Modes[giBGA_CurrentMode].width * giVT_CharWidth; + int x, y; + Uint32 *dest; + + off /= sizeof(tVT_Char); + dest = (void*)gBGA_Framebuffer; + x = (off % gBGA_Modes[giBGA_CurrentMode].width) * giVT_CharWidth; + y = (off / gBGA_Modes[giBGA_CurrentMode].width) * giVT_CharHeight; + dest += y * pitch; + dest += x * giVT_CharWidth; + len /= sizeof(tVT_Char); + while(len--) + { + VT_Font_Render( + chars->Ch, + dest, pitch, + VT_Colour12to24(chars->BGCol), + VT_Colour12to24(chars->FGCol) + ); + + dest += giVT_CharWidth; + + chars ++; + x += giVT_CharWidth; + if( x >= pitch ) { + x = 0; + y += giVT_CharHeight; + dest += pitch*(giVT_CharHeight-1); + } + } + } + else + { + Uint8 *destBuf = (Uint8*) ((Uint)gBGA_Framebuffer + (Uint)off); + + LOG("buffer = %p\n", buffer); + LOG("Updating Framebuffer (%p to %p)\n", + destBuf, destBuf + (Uint)len); + + + // Copy to Frambuffer + memcpy(destBuf, buffer, len); + + LOG("BGA Framebuffer updated\n"); + } + + LEAVE('i', len); + return len; +} + +/** + * \fn INT int BGA_Ioctl(tVFS_Node *node, int ID, void *Data) + * \brief Handle messages to the device + */ +INT int BGA_Ioctl(tVFS_Node *node, int ID, void *Data) +{ + int ret = -2; + ENTER("pNode iId pData", node, ID, Data); + + switch(ID) + { + case DRV_IOCTL_TYPE: + ret = DRV_TYPE_VIDEO; + break; + case DRV_IOCTL_IDENT: + memcpy(Data, "BGA1", 4); + ret = 1; + break; + case DRV_IOCTL_VERSION: + ret = 0x100; + break; + case DRV_IOCTL_LOOKUP: // TODO: Implement + ret = 0; + break; + + case VIDEO_IOCTL_SETMODE: + ret = BGA_int_UpdateMode(*(int*)(Data)); + break; + + case VIDEO_IOCTL_GETMODE: + ret = giBGA_CurrentMode; + break; + + case VIDEO_IOCTL_FINDMODE: + ret = BGA_int_FindMode((tVideo_IOCtl_Mode*)Data); + break; + + case VIDEO_IOCTL_MODEINFO: + ret = BGA_int_ModeInfo((tVideo_IOCtl_Mode*)Data); + break; + + // Request Access to LFB + case VIDEO_IOCTL_REQLFB: + ret = BGA_int_MapFB( *(void**)Data ); + break; + + case VIDEO_IOCTL_SETCURSOR: + gBGA_CursorPos.x = ((tVideo_IOCtl_Pos*)Data)->x; + gBGA_CursorPos.y = ((tVideo_IOCtl_Pos*)Data)->y; + break; + + default: + LEAVE('i', -2); + return -2; + } + + LEAVE('i', ret); + return ret; +} + +//== Internal Functions == +/** + * \fn void BGA_int_WriteRegister(Uint16 reg, Uint16 value) + * \brief Writes to a BGA register + */ +void BGA_int_WriteRegister(Uint16 reg, Uint16 value) +{ + outw(VBE_DISPI_IOPORT_INDEX, reg); + outw(VBE_DISPI_IOPORT_DATA, value); +} + +INT Uint16 BGA_int_ReadRegister(Uint16 reg) +{ + outw(VBE_DISPI_IOPORT_INDEX, reg); + return inw(VBE_DISPI_IOPORT_DATA); +} + +#if 0 +INT void BGA_int_SetBank(Uint16 bank) +{ + BGA_int_WriteRegister(VBE_DISPI_INDEX_BANK, bank); +} +#endif + +/** + * \fn void BGA_int_SetMode(Uint16 width, Uint16 height, Uint16 bpp) + * \brief Sets the video mode from the dimensions and bpp given + */ +void BGA_int_SetMode(Uint16 width, Uint16 height) +{ + ENTER("iwidth iheight ibpp", width, height, bpp); + BGA_int_WriteRegister(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_DISABLED); + BGA_int_WriteRegister(VBE_DISPI_INDEX_XRES, width); + BGA_int_WriteRegister(VBE_DISPI_INDEX_YRES, height); + BGA_int_WriteRegister(VBE_DISPI_INDEX_BPP, 32); + BGA_int_WriteRegister(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_ENABLED | VBE_DISPI_NOCLEARMEM | VBE_DISPI_LFB_ENABLED); + //BGA_int_WriteRegister(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_ENABLED | VBE_DISPI_NOCLEARMEM); + LEAVE('-'); +} + +/** + * \fn int BGA_int_UpdateMode(int id) + * \brief Set current vide mode given a mode id + */ +int BGA_int_UpdateMode(int id) +{ + // Sanity Check + if(id < 0 || id >= BGA_MODE_COUNT) return -1; + + // Check if it is a text mode + if( gBGA_Modes[id].flags & MODEFLAG_TEXT ) + BGA_int_SetMode( + gBGA_Modes[id].width*giVT_CharWidth, + gBGA_Modes[id].height*giVT_CharHeight); + else // Graphics? + BGA_int_SetMode( + gBGA_Modes[id].width, + gBGA_Modes[id].height); + + giBGA_CurrentMode = id; + return id; +} + +/** + * \fn int BGA_int_FindMode(tVideo_IOCtl_Mode *info) + * \brief Find a mode matching the given options + */ +int BGA_int_FindMode(tVideo_IOCtl_Mode *info) +{ + int i; + int best = 0, bestFactor = 1000; + int factor, tmp; + int rqdProduct = info->width * info->height * info->bpp; + + ENTER("pinfo", info); + LOG("info = {width:%i,height:%i,bpp:%i})\n", info->width, info->height, info->bpp); + + for(i = 0; i < BGA_MODE_COUNT; i++) + { + #if DEBUG >= 2 + LogF("Mode %i (%ix%ix%i), ", i, gBGA_Modes[i].width, gBGA_Modes[i].height, gBGA_Modes[i].bpp); + #endif + + // Check if this mode is the same type as what we want + if( !(gBGA_Modes[i].flags & MODEFLAG_TEXT) != !(info->flags & VIDEO_FLAG_TEXT) ) + continue; + + // Ooh! A perfect match + if(gBGA_Modes[i].width == info->width + && gBGA_Modes[i].height == info->height + && gBGA_Modes[i].bpp == info->bpp) + { + #if DEBUG >= 2 + LogF("Perfect!\n"); + #endif + best = i; + break; + } + + // If not, how close are we? + tmp = gBGA_Modes[i].width * gBGA_Modes[i].height * gBGA_Modes[i].bpp; + tmp -= rqdProduct; + tmp = tmp < 0 ? -tmp : tmp; // tmp = ABS(tmp) + factor = tmp * 100 / rqdProduct; + + #if DEBUG >= 2 + LogF("factor = %i\n", factor); + #endif + + if(factor < bestFactor) + { + bestFactor = factor; + best = i; + } + } + + info->id = best; + info->width = gBGA_Modes[best].width; + info->height = gBGA_Modes[best].height; + info->bpp = gBGA_Modes[best].bpp; + + info->flags = 0; + if(gBGA_Modes[best].flags & MODEFLAG_TEXT) + info->flags |= VIDEO_FLAG_TEXT; + + return best; +} + +/** + * \fn int BGA_int_ModeInfo(tVideo_IOCtl_Mode *info) + * \brief Get mode information + */ +int BGA_int_ModeInfo(tVideo_IOCtl_Mode *info) +{ + // Sanity Check + //if( !MM_IsUser( (Uint)info, sizeof(tVideo_IOCtl_Mode) ) ) { + // return -EINVAL; + //} + + if(info->id < 0 || info->id >= BGA_MODE_COUNT) return -1; + + info->width = gBGA_Modes[info->id].width; + info->height = gBGA_Modes[info->id].height; + info->bpp = gBGA_Modes[info->id].bpp; + + info->flags = 0; + if(gBGA_Modes[info->id].flags & MODEFLAG_TEXT) + info->flags |= VIDEO_FLAG_TEXT; + + return 1; +} + +/** + * \fn int BGA_int_MapFB(void *Dest) + * \brief Map the framebuffer into a process's space + * \param Dest User address to load to + */ +int BGA_int_MapFB(void *Dest) +{ + Uint i; + Uint pages; + + // Sanity Check + if((Uint)Dest > 0xC0000000) return 0; + if(gBGA_Modes[giBGA_CurrentMode].bpp < 15) return 0; // Only non-pallete modes are supported + + // Count required pages + pages = (gBGA_Modes[giBGA_CurrentMode].fbSize + 0xFFF) >> 12; + + // Check if there is space + for( i = 0; i < pages; i++ ) + { + if(MM_GetPhysAddr( (Uint)Dest + (i << 12) )) + return 0; + } + + // Map + for( i = 0; i < pages; i++ ) + MM_Map( (Uint)Dest + (i<<12), VBE_DISPI_LFB_PHYSICAL_ADDRESS + (i<<12) ); + + return 1; +} diff --git a/Modules/IPStack/link.h b/Modules/IPStack/link.h index c662f141..d96008d4 100644 --- a/Modules/IPStack/link.h +++ b/Modules/IPStack/link.h @@ -10,6 +10,7 @@ typedef void (*tPacketCallback)(tAdapter *Interface, tMacAddr From, int Length, extern void Link_RegisterType(Uint16 Type, tPacketCallback Callback); extern void Link_SendPacket(tAdapter *Interface, Uint16 Type, tMacAddr To, int Length, void *Buffer); +extern void Link_WatchDevice(tAdapter *Adapter); // === INTERNAL === typedef struct sEthernetHeader tEthernetHeader; diff --git a/Modules/IPStack/main.c b/Modules/IPStack/main.c index 051d064d..5a250fb7 100644 --- a/Modules/IPStack/main.c +++ b/Modules/IPStack/main.c @@ -5,6 +5,7 @@ #define DEBUG 0 #define VERSION ((0<<8)|10) #include "ipstack.h" +#include "link.h" #include #include #include @@ -31,12 +32,14 @@ tDevFS_Driver gIP_DriverInfo = { .ACLs = &gVFS_ACL_EveryoneRX, .Flags = VFS_FFLAG_DIRECTORY, .ReadDir = IPStack_ReadDir, - .FindDir = IPStack_FindDir + .FindDir = IPStack_FindDir, + .IOCtl = IPStack_IOCtl } }; int glIP_Interfaces = 0; tInterface *gIP_Interfaces = NULL; tInterface *gIP_Interfaces_Last = NULL; + int giIP_NextIfaceId = 1; int glIP_Adapters = 0; tAdapter *gIP_Adapters = NULL; @@ -63,6 +66,8 @@ int IPStack_Install(char **Arguments) } } + DevFS_AddDevice( &gIP_DriverInfo ); + return 1; } @@ -72,22 +77,33 @@ int IPStack_Install(char **Arguments) char *IPStack_ReadDir(tVFS_Node *Node, int Pos) { tInterface *iface; - char name[5] = "ip0\0\0"; + char name[] = "ip0\0\0\0"; + ENTER("pNode iPos", Node, Pos); + + // Traverse the list + for( iface = gIP_Interfaces; iface && Pos--; iface = iface->Next ) ; + + // Did we run off the end? + if(!iface) { + LEAVE('n'); + return NULL; + } // Create the name + Pos = iface->Node.ImplInt; if(Pos < 10) name[2] = '0' + Pos; - else { + else if(Pos < 100) { name[2] = '0' + Pos/10; name[3] = '0' + Pos%10; } + else { + name[2] = '0' + Pos/100; + name[3] = '0' + (Pos/10)%10; + name[4] = '0' + Pos%10; + } - // Traverse the list - for( iface = gIP_Interfaces; iface && Pos--; iface = iface->Next ) ; - - // Did we run off the end? - if(!iface) return NULL; - + LEAVE('s', name); // Return the pre-generated name return strdup(name); } @@ -97,27 +113,38 @@ char *IPStack_ReadDir(tVFS_Node *Node, int Pos) */ tVFS_Node *IPStack_FindDir(tVFS_Node *Node, char *Name) { - int i; - tInterface *iface; + int i, num; + tInterface *iface; - if(Name[0] != 'i' || Name[1] != 'p') return NULL; - if(Name[2] < '0' || Name[2] > '9') return NULL; + ENTER("pNode sName", Node, Name); - 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[0] != 'i' || Name[1] != 'p') { + LEAVE('n'); + return NULL; } - if(Name[3] < '0' || Name[3] > '9') return NULL; - - i = (Name[2] - '0')*10; - i += Name[3] - '0'; + i = 2; num = 0; + while('0' <= Name[i] && Name[i] <= '9') + { + num *= 10; + num += Name[i] - '0'; + i ++; + } + if(Name[i] != '\0') { + LEAVE('n'); + return NULL; + } - for( iface = gIP_Interfaces; iface && i--; iface = iface->Next ) ; - if(!iface) return NULL; - return &iface->Node; + for( iface = gIP_Interfaces; iface; iface = iface->Next ) + { + if( iface->Node.ImplInt == num ) + { + LEAVE('p', &iface->Node); + return &iface->Node; + } + } + LEAVE('p', NULL); + return NULL; } static const char *casIOCtls_Root[] = { DRV_IOCTLNAMES, "add_interface", NULL }; @@ -134,27 +161,35 @@ static const char *casIOCtls_Iface[] = { */ int IPStack_IOCtl(tVFS_Node *Node, int ID, void *Data) { + int tmp; + ENTER("pNode iID pData", Node, ID, Data); + switch(ID) { // --- Standard IOCtls (0-3) --- case DRV_IOCTL_TYPE: + LEAVE('i', DRV_TYPE_MISC); return DRV_TYPE_MISC; case DRV_IOCTL_IDENT: - if( !CheckMem( Data, 4 ) ) return -1; + if( !CheckMem( Data, 4 ) ) LEAVE_RET('i', -1); memcpy(Data, "IP\0\0", 4); + LEAVE('i', 1); return 1; case DRV_IOCTL_VERSION: + LEAVE('x', VERSION); return VERSION; case DRV_IOCTL_LOOKUP: - if( !CheckString( Data ) ) return -1; - + if( !CheckString( Data ) ) LEAVE_RET('i', -1); + LOG("Lookup '%s'", Data); if( Node == &gIP_DriverInfo.RootNode ) - return LookupString( (char**)casIOCtls_Root, (char*)Data ); + tmp = LookupString( (char**)casIOCtls_Root, (char*)Data ); else - return LookupString( (char**)casIOCtls_Iface, (char*)Data ); + tmp = LookupString( (char**)casIOCtls_Iface, (char*)Data ); + LEAVE('i', tmp); + return tmp; } if(Node == &gIP_DriverInfo.RootNode) @@ -166,10 +201,12 @@ int IPStack_IOCtl(tVFS_Node *Node, int ID, void *Data) * - Adds a new IP interface and binds it to a device */ case 4: - if( Threads_GetUID() != 0 ) return -1; - if( !CheckString( Data ) ) return -1; - return IPStack_AddInterface(Data); + if( Threads_GetUID() != 0 ) LEAVE_RET('i', -1); + if( !CheckString( Data ) ) LEAVE_RET('i', -1); + tmp = IPStack_AddInterface(Data); + LEAVE_RET('i', tmp); } + LEAVE('i', 0); return 0; } else @@ -182,29 +219,41 @@ int IPStack_IOCtl(tVFS_Node *Node, int ID, void *Data) * - Get/Set the interface type */ case 4: - // Get Type? - if( !Data ) return iface->Type; - // Ok, it's set type - if( Threads_GetUID() != 0 ) return -1; - if( !CheckMem( Data, sizeof(int) ) ) return -1; - switch( *(int*)Data ) + // Set Type? + if( Data ) { - case 0: // Disable - iface->Type = 0; - memset(&iface->IP6, 0, sizeof(tIPv6)); // Clear address - break; - case 4: // IPv4 - iface->Type = 4; - memset(&iface->IP4, 0, sizeof(tIPv4)); - break; - case 6: // IPv6 - iface->Type = 6; - memset(&iface->IP6, 0, sizeof(tIPv6)); - break; - default: - return -1; + // Ok, it's set type + if( Threads_GetUID() != 0 ) { + LOG("Attempt by non-root to alter an interface (%i)", Threads_GetUID()); + LEAVE('i', -1); + return -1; + } + if( !CheckMem( Data, sizeof(int) ) ) { + LOG("Invalid pointer %p", Data); + LEAVE('i', -1); + return -1; + } + switch( *(int*)Data ) + { + case 0: // Disable + iface->Type = 0; + memset(&iface->IP6, 0, sizeof(tIPv6)); // Clear address + break; + case 4: // IPv4 + iface->Type = 4; + memset(&iface->IP4, 0, sizeof(tIPv4)); + break; + case 6: // IPv6 + iface->Type = 6; + memset(&iface->IP6, 0, sizeof(tIPv6)); + break; + default: + LEAVE('i', -1); + return -1; + } } - return 0; + LEAVE('i', iface->Type); + return iface->Type; /* * get_address @@ -213,41 +262,41 @@ int IPStack_IOCtl(tVFS_Node *Node, int ID, void *Data) case 5: switch(iface->Type) { - case 0: return 1; + case 0: LEAVE_RET('i', 1); case 4: - if( !CheckMem( Data, sizeof(tIPv4) ) ) return -1; - memcpy( Data, &iface->IP4, sizeof(tIPv4) ); - return 1; + if( !CheckMem( Data, sizeof(tIPv4) ) ) LEAVE_RET('i', -1); + memcpy( Data, &iface->IP4.Address, sizeof(tIPv4) ); + LEAVE_RET('i', 1); case 6: - if( !CheckMem( Data, sizeof(tIPv6) ) ) return -1; - memcpy( Data, &iface->IP6, sizeof(tIPv6) ); - return 1; + if( !CheckMem( Data, sizeof(tIPv6) ) ) LEAVE_RET('i', -1); + memcpy( Data, &iface->IP6.Address, sizeof(tIPv6) ); + LEAVE_RET('i', 1); } - return 0; + LEAVE_RET('i', 0); /* * set_address * - Get the interface's address */ case 6: - if( Threads_GetUID() != 0 ) return -1; + if( Threads_GetUID() != 0 ) LEAVE_RET('i', -1); switch(iface->Type) { - case 0: return 1; + case 0: LEAVE_RET('i', 1); case 4: - if( !CheckMem( Data, sizeof(tIPv4) ) ) return -1; + if( !CheckMem( Data, sizeof(tIPv4) ) ) LEAVE_RET('i', -1); iface->Type = 0; // One very hacky mutex/trash protector - memcpy( &iface->IP4, Data, sizeof(tIPv4) ); + memcpy( &iface->IP4.Address, Data, sizeof(tIPv4) ); iface->Type = 4; - return 1; + LEAVE_RET('i', 1); case 6: - if( !CheckMem( Data, sizeof(tIPv6) ) ) return -1; + if( !CheckMem( Data, sizeof(tIPv6) ) ) LEAVE_RET('i', -1); iface->Type = 0; - memcpy( &iface->IP6, Data, sizeof(tIPv6) ); + memcpy( &iface->IP6.Address, Data, sizeof(tIPv6) ); iface->Type = 6; - return 1; + LEAVE_RET('i', 1); } - return 0; + LEAVE_RET('i', 0); /* * getset_subnet @@ -259,35 +308,79 @@ int IPStack_IOCtl(tVFS_Node *Node, int ID, void *Data) { switch( iface->Type ) { - case 4: return iface->IP4.SubnetBits; - case 6: return iface->IP6.SubnetBits; - default: return 0; + case 4: LEAVE_RET('i', iface->IP4.SubnetBits); + case 6: LEAVE_RET('i', iface->IP6.SubnetBits); + default: LEAVE_RET('i', 0); } } // Ok, set. - if( Threads_GetUID() != 0 ) return -1; - if( !CheckMem(Data, sizeof(int)) ) return -1; + if( Threads_GetUID() != 0 ) LEAVE_RET('i', -1); + if( !CheckMem(Data, sizeof(int)) ) LEAVE_RET('i', -1); // Check and set the subnet bits switch( iface->Type ) { case 4: - if( *(int*)Data < 0 || *(int*)Data > 31 ) return -1; + if( *(int*)Data < 0 || *(int*)Data > 31 ) LEAVE_RET('i', -1); iface->IP4.SubnetBits = *(int*)Data; - return iface->IP4.SubnetBits; + LEAVE_RET('i', iface->IP4.SubnetBits); case 6: - if( *(int*)Data < 0 || *(int*)Data > 127 ) return -1; + if( *(int*)Data < 0 || *(int*)Data > 127 ) LEAVE_RET('i', -1); iface->IP6.SubnetBits = *(int*)Data; - return iface->IP6.SubnetBits; + LEAVE_RET('i', iface->IP6.SubnetBits); default: break; } + LEAVE('i', 0); + return 0; + + /* + * get_gateway + * - Get the interface's IPv4 gateway + */ + case 8: + switch(iface->Type) + { + case 0: + LEAVE_RET('i', 1); + case 4: + if( !CheckMem( Data, sizeof(tIPv4) ) ) LEAVE_RET('i', -1); + memcpy( Data, &iface->IP4.Gateway, sizeof(tIPv4) ); + LEAVE_RET('i', 1); + case 6: + LEAVE_RET('i', 1); + } + LEAVE('i', 0); return 0; + + /* + * set_gateway + * - Get the interface's IPv4 gateway + */ + case 9: + if( Threads_GetUID() != 0 ) LEAVE_RET('i', -1); + switch(iface->Type) + { + case 0: + LEAVE_RET('i', 1); + + case 4: + if( !CheckMem( Data, sizeof(tIPv4) ) ) LEAVE_RET('i', -1); + iface->Type = 0; // One very hacky mutex/trash protector + memcpy( &iface->IP4.Gateway, Data, sizeof(tIPv4) ); + iface->Type = 4; + LEAVE_RET('i', 1); + + case 6: + LEAVE_RET('i', 1); + } + LEAVE_RET('i', 0); } } + LEAVE('i', 0); return 0; } @@ -300,24 +393,33 @@ int IPStack_AddInterface(char *Device) { tInterface *iface; + ENTER("sDevice", Device); + iface = malloc(sizeof(tInterface)); - if(!iface) return -2; // Return ERR_MYBAD + if(!iface) { + LEAVE('i', -2); + return -2; // Return ERR_MYBAD + } iface->Next = NULL; iface->Type = 0; // Unset type // Create Node + iface->Node.ImplPtr = iface; + iface->Node.ImplInt = giIP_NextIfaceId++; 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; + iface->Node.IOCtl = IPStack_IOCtl; // Get adapter handle iface->Adapter = IPStack_GetAdapter(Device); if( !iface->Adapter ) { free( iface ); + LEAVE('i', -1); return -1; // Return ERR_YOUFAIL } @@ -333,8 +435,11 @@ int IPStack_AddInterface(char *Device) } RELEASE( &glIP_Interfaces ); + gIP_DriverInfo.RootNode.Size ++; + // Success! - return 1; + LEAVE('i', iface->Node.ImplInt); + return iface->Node.ImplInt; } /** @@ -344,6 +449,9 @@ int IPStack_AddInterface(char *Device) tAdapter *IPStack_GetAdapter(char *Path) { tAdapter *dev; + int tmp; + + ENTER("sPath", Path); LOCK( &glIP_Adapters ); @@ -353,6 +461,7 @@ tAdapter *IPStack_GetAdapter(char *Path) if( strcmp(dev->Device, Path) == 0 ) { dev->NRef ++; RELEASE( &glIP_Adapters ); + LEAVE('p', dev); return dev; } } @@ -361,6 +470,7 @@ tAdapter *IPStack_GetAdapter(char *Path) dev = malloc( sizeof(tAdapter) + strlen(Path) + 1 ); if(!dev) { RELEASE( &glIP_Adapters ); + LEAVE('n'); return NULL; } @@ -373,15 +483,19 @@ tAdapter *IPStack_GetAdapter(char *Path) if( dev->DeviceFD == -1 ) { free( dev ); RELEASE( &glIP_Adapters ); + LEAVE('n'); return NULL; } // Check that it is a network interface - if( VFS_IOCtl(dev->DeviceFD, 0, NULL) != DRV_TYPE_NETWORK ) { + tmp = VFS_IOCtl(dev->DeviceFD, 0, NULL); + LOG("Device type = %i", tmp); + if( tmp != DRV_TYPE_NETWORK ) { Warning("IPStack_GetAdapter: '%s' is not a network interface", dev->Device); VFS_Close( dev->DeviceFD ); free( dev ); RELEASE( &glIP_Adapters ); + LEAVE('n'); return NULL; } @@ -393,5 +507,10 @@ tAdapter *IPStack_GetAdapter(char *Path) gIP_Adapters = dev; RELEASE( &glIP_Adapters ); + + // Start watcher + Link_WatchDevice( dev ); + + LEAVE('p', dev); return dev; } diff --git a/Modules/Makefile.tpl b/Modules/Makefile.tpl index a9a6d8db..2484610d 100644 --- a/Modules/Makefile.tpl +++ b/Modules/Makefile.tpl @@ -5,7 +5,7 @@ -include ../../Makefile.cfg CPPFLAGS = -I../../Kernel/include -I../../Kernel/arch/$(ARCHDIR)/include -DARCH=$(ARCH) -CFLAGS = -Wall -Werror $(CPPFLAGS) +CFLAGS = -Wall -Werror -fno-stack-protector $(CPPFLAGS) OBJ := $(addsuffix .$(ARCH),$(OBJ)) BIN = ../$(NAME).kmd.$(ARCH) @@ -19,12 +19,13 @@ DEPFILES := $(DEPFILES:%.o.$(ARCH)=%.d.$(ARCH)) all: $(BIN) clean: - $(RM) $(BIN) $(KOBJ) $(OBJ) $(DEPFILES) + $(RM) $(BIN) $(BIN).dsm $(KOBJ) $(OBJ) $(DEPFILES) $(BIN): $(OBJ) @echo --- $(LD) -o $@ @$(LD) -T ../link.ld -shared -nostdlib -o $@ $(OBJ) # @$(LD) -shared -nostdlib -o $@ $(OBJ) + @$(OBJDUMP) -d $(BIN) > $(BIN).dsm cp $@ $(DISTROOT)/Modules/$(NAME).kmd @echo --- $(LD) -o $(KOBJ) @$(CC) -Wl,-r -nostdlib -o $(KOBJ) $(OBJ) diff --git a/Modules/NE2000/ne2000.c b/Modules/NE2000/ne2000.c index 225a0219..3717a99c 100644 --- a/Modules/NE2000/ne2000.c +++ b/Modules/NE2000/ne2000.c @@ -9,6 +9,7 @@ #include #include #include +#include // === CONSTANTS === #define MEM_START 0x40 @@ -91,7 +92,8 @@ tDevFS_Driver gNe2k_DriverInfo = { .ACLs = &gVFS_ACL_EveryoneRX, .Flags = VFS_FFLAG_DIRECTORY, .ReadDir = Ne2k_ReadDir, - .FindDir = Ne2k_FindDir + .FindDir = Ne2k_FindDir, + .IOCtl = Ne2k_IOCtl } }; Uint16 gNe2k_BaseAddress; @@ -233,30 +235,56 @@ static const char *casIOCtls[] = { DRV_IOCTLNAMES, DRV_NETWORK_IOCTLNAMES, NULL */ int Ne2k_IOCtl(tVFS_Node *Node, int ID, void *Data) { + int tmp; + ENTER("pNode iID pData", Node, ID, Data); switch( ID ) { - case DRV_IOCTL_TYPE: return DRV_TYPE_NETWORK; + case DRV_IOCTL_TYPE: + LEAVE('i', DRV_TYPE_NETWORK); + return DRV_TYPE_NETWORK; + case DRV_IOCTL_IDENT: - if(!CheckMem(Data, 4)) return -1; + if(!CheckMem(Data, 4)) { + LEAVE('i', -1); + return -1; + } memcpy(Data, "NE2K", 4); + LEAVE('i', 1); return 1; - case DRV_IOCTL_VERSION: return VERSION; + + case DRV_IOCTL_VERSION: + LEAVE('x', VERSION); + return VERSION; + case DRV_IOCTL_LOOKUP: - if(!CheckString(Data)) return -1; - return LookupString( casIOCtls, Data ); + if( !CheckString(Data) ) { + LEAVE('i', -1); + return -1; + } + tmp = LookupString( (char**)casIOCtls, Data ); + LEAVE('i', tmp); + return tmp; } // If this is the root, return - if( Node == &gNe2k_DriverInfo.Node ) return 0; + if( Node == &gNe2k_DriverInfo.RootNode ) { + LEAVE('i', 0); + return 0; + } // Device specific settings switch( ID ) { case NET_IOCTL_GETMAC: - if(!CheckMem(Data, 6)) return -1; + if( !CheckMem(Data, 6) ) { + LEAVE('i', -1); + return -1; + } memcpy( Data, ((tCard*)Node->ImplPtr)->MacAddr, 6 ); + LEAVE('i', 1); return 1; } + LEAVE('i', 0); return 0; } diff --git a/Usermode/Applications/ifconfig_src/Makefile b/Usermode/Applications/ifconfig_src/Makefile new file mode 100644 index 00000000..75e95193 --- /dev/null +++ b/Usermode/Applications/ifconfig_src/Makefile @@ -0,0 +1,27 @@ +# Project: ifconfig + +-include ../Makefile.cfg + +COBJ = main.o +BIN = ../ifconfig + +CFLAGS += -Wall -fno-builtin -fno-stack-protector +LDFLAGS += + +.PHONY : all clean + +all: $(BIN) + +$(BIN): $(COBJ) + @echo --- $(LD) -o $@ + @$(LD) $(LDFLAGS) -o $@ $(COBJ) -Map Map.txt + @objdump -d $(BIN) > $(BIN).dsm + cp $(BIN) $(DISTROOT)/Bin/ + +clean: + @$(RM) $(COBJ) $(BIN) $(BIN).dsm Map.txt + +$(COBJ): %.o: %.c + @echo --- GCC -o $@ + @$(CC) $(CFLAGS) -c $? -o $@ + diff --git a/Usermode/Applications/ifconfig_src/main.c b/Usermode/Applications/ifconfig_src/main.c new file mode 100644 index 00000000..47798a83 --- /dev/null +++ b/Usermode/Applications/ifconfig_src/main.c @@ -0,0 +1,171 @@ +/* + * Acess2 IFCONFIG command + */ +#include +#include +#include +#include + +// === CONSTANTS === +#define FILENAME_MAX 255 +#define IPSTACK_ROOT "/Devices/ip" + +// === PROTOTYPES === +void PrintUsage(char *ProgName); +void DumpInterfaces( int DumpAll ); + int AddInterface( char *Address ); + int DoAutoConfig( char *Device ); + +// === CODE === +/** + * \fn int main(int argc, char *argv[]) + * \brief Entrypoint + */ +int main(int argc, char *argv[]) +{ + if(argc == 1) { + DumpInterfaces(0); + return 0; + } + + if( strcmp(argv[1], "add") == 0 ) { + if( argc < 3 ) { + fprintf(stderr, "ERROR: `add` requires an argument\n"); + PrintUsage(argv[0]); + return 0; + } + return AddInterface( argv[2] ); + } + + if( strcmp(argv[1], "autoconf") == 0 ) { + DoAutoConfig(argv[2]); + } + + return 0; +} + +void PrintUsage(char *ProgName) +{ + fprintf(stderr, "Usage: %s [add ]\n", ProgName); +} + +void DumpInterfaces(int DumpAll) +{ + int dp, fd; + int type; + char path[sizeof(IPSTACK_ROOT)+1+FILENAME_MAX] = IPSTACK_ROOT"/"; + char *filename = &path[sizeof(IPSTACK_ROOT)]; + + dp = open(IPSTACK_ROOT, OPENFLAG_READ); + + while( readdir(dp, filename) ) + { + if(filename[0] == '.') continue; + if(filename[0] != 'i' || filename[1] != 'p') continue; + + fd = open(path, OPENFLAG_READ); + if(fd == -1) { + printf("%s:\tUnable to open ('%s'\n\n", filename, path); + } + + type = ioctl(fd, 4, NULL); + + printf("%s:\t", filename); + switch(type) + { + case 0: + printf("DISABLED\n"); + break; + case 4: + { + uint8_t ip[4]; + int subnet; + printf("IPv4\n"); + ioctl(fd, 5, ip); // Get IP Address + subnet = ioctl(fd, 7, NULL); // Get Subnet Bits + printf("\t%i.%i.%i.%i/%i\n", ip[0], ip[1], ip[2], ip[3], subnet); + ioctl(fd, 8, ip); // Get Gateway + printf("\tGateway: %i.%i.%i.%i\n", ip[0], ip[1], ip[2], ip[3]); + } + break; + case 6: + { + uint16_t ip[8]; + int subnet; + printf("IPv6\n"); + ioctl(fd, 5, ip); // Get IP Address + subnet = ioctl(fd, 7, NULL); // Get Subnet Bits + printf("\t%x:%x:%x:%x:%x:%x:%x:%x/%i\n", + ip[0], ip[1], ip[2], ip[3], + ip[4], ip[5], ip[6], ip[7], + subnet); + } + break; + default: + printf("UNKNOWN\n"); + break; + } + printf("\n"); + + close(fd); + } + + close(dp); +} + +int AddInterface( char *Device ) +{ + int dp, ret; + + dp = open(IPSTACK_ROOT, OPENFLAG_READ); + ret = ioctl(dp, 4, Device); + close(dp); + + if( ret < 0 ) { + fprintf(stderr, "Unable to add '%s' as a network interface\n", Device); + return -1; + } + + printf("-- Added '"IPSTACK_ROOT"/ip%i' using device %s\n", ret, Device); + + return ret; +} + +int DoAutoConfig( char *Device ) +{ + int tmp, fd; + char path[sizeof(IPSTACK_ROOT)+5+1]; // ip000 + uint8_t addr[4] = {192,168,1,39}; + uint8_t gw[4] = {192,168,1,1}; + + tmp = AddInterface(Device); + if( tmp < 0 ) return tmp; + + sprintf(path, IPSTACK_ROOT"/ip%i", tmp); + + fd = open(path, OPENFLAG_READ); + if( fd == -1 ) { + fprintf(stderr, "Unable to open '%s'\n", path); + return -1; + } + + tmp = 4; // IPv4 + tmp = ioctl(fd, ioctl(fd, 3, "getset_type"), &tmp); + if( tmp != 4 ) { + fprintf(stderr, "Error in setting address type (got %i, expected 4)\n", tmp); + return -1; + } + // Set Address + ioctl(fd, ioctl(fd, 3, "set_address"), addr); + // Set Subnet + tmp = 24; + ioctl(fd, ioctl(fd, 3, "getset_subnet"), &tmp); + // Set Gateway + ioctl(fd, ioctl(fd, 3, "set_gateway"), gw); + + close(fd); + + printf("Set address to 192.168.1.39/24 (GW: 192.168.1.1)\n"); + + return 0; +} -- 2.20.1